X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Document.cpp;h=4bf71d0346a33bc709a7d05e9d0c4cc0b3a6860f;hb=5ee0ac732ede71b1a7784be6870c5f21f6782565;hp=c471c2a7119e238f515408632d5b74aedb4773ae;hpb=3ad1f9b6d79cb4512840c457d86e53f5da8b310f;p=modules%2Fshaper.git diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index c471c2a71..4bf71d034 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -6,14 +6,11 @@ #include #include +#include #include #include #include -#include -#include -#include -#include -#include +#include #include #include @@ -46,22 +43,15 @@ static const int UNDO_LIMIT = 1000; // number of possible undo operations (big for sketcher) static const int TAG_GENERAL = 1; // general properties tag -static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, results) -static const int TAG_HISTORY = 3; // tag of the history sub-tree (python dump) -// feature sub-labels -static const int TAG_FEATURE_ARGUMENTS = 1; ///< where the arguments are located -static const int TAG_FEATURE_RESULTS = 2; ///< where the results are located - -/// -/// 0:1:2 - where features are located -/// 0:1:2:N:1 - data of the feature N -/// 0:1:2:N:2:K:1 - data of the K result of the feature N +// general sub-labels +static const int TAG_CURRENT_FEATURE = 1; ///< where the reference to the current feature label is located (or no attribute if null feature) Model_Document::Model_Document(const std::string theID, const std::string theKind) : myID(theID), myKind(theKind), myDoc(new TDocStd_Document("BinOcaf")) // binary OCAF format { + myObjs = new Model_Objects(myDoc->Main()); myDoc->SetUndoLimit(UNDO_LIMIT); myTransactionSave = 0; myExecuteFeatures = true; @@ -72,6 +62,11 @@ Model_Document::Model_Document(const std::string theID, const std::string theKin myDoc->CommitCommand(); } +void Model_Document::setThis(DocumentPtr theDoc) +{ + myObjs->setOwner(theDoc); +} + /// Returns the file name of this document by the nameof directory and identifuer of a document static TCollection_ExtendedString DocFileName(const char* theFileName, const std::string& theID) { @@ -91,7 +86,7 @@ bool Model_Document::isRoot() const return this == Model_Session::get()->moduleDocument().get(); } -bool Model_Document::load(const char* theFileName) +bool Model_Document::load(const char* theFileName, DocumentPtr theThis) { Handle(Model_Application) anApp = Model_Application::getApplication(); if (isRoot()) { @@ -168,7 +163,12 @@ bool Model_Document::load(const char* theFileName) std::dynamic_pointer_cast(Model_Session::get()); aSession->setActiveDocument(anApp->getDocument(myID), false); aSession->setCheckTransactions(false); - synchronizeFeatures(false, true, true); + if (myObjs) + delete myObjs; + myObjs = new Model_Objects(myDoc->Main()); // synchronisation is inside + myObjs->setOwner(theThis); + // update the current features status + setCurrentFeature(currentFeature(false), false); aSession->setCheckTransactions(true); aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false); aSession->setActiveDocument(anApp->getDocument(myID), true); @@ -263,33 +263,14 @@ void Model_Document::close(const bool theForever) // close for thid document needs no transaction in this document std::static_pointer_cast(Model_Session::get())->setCheckTransactions(false); - // delete all features of this document - std::shared_ptr aThis = - Model_Application::getApplication()->getDocument(myID); - Events_Loop* aLoop = Events_Loop::loop(); - NCollection_DataMap::Iterator aFeaturesIter(myObjs); - for(; aFeaturesIter.More(); aFeaturesIter.Next()) { - FeaturePtr aFeature = aFeaturesIter.Value(); - static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); - ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group()); - ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP); - aFeature->eraseResults(); - if (theForever) { // issue #294: do not delete content of the document until it can be redone - aFeature->erase(); - } else { - aFeature->data()->execState(ModelAPI_StateMustBeUpdated); - } - } - if (theForever) { - myObjs.Clear(); - } - aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED)); - aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); - // close all only if it is really asked, otherwise it can be undoed/redoed if (theForever) { + delete myObjs; + myObjs = 0; if (myDoc->CanClose() == CDM_CCS_OK) myDoc->Close(); + } else { + setCurrentFeature(FeaturePtr(), false); // disables all features } std::static_pointer_cast(Model_Session::get())->setCheckTransactions(true); @@ -338,7 +319,7 @@ bool Model_Document::finishOperation() bool isNestedClosed = !myDoc->HasOpenCommand() && !myNestedNum.empty(); static std::shared_ptr aSession = std::static_pointer_cast(Model_Session::get()); - synchronizeBackRefs(); + myObjs->synchronizeBackRefs(); Events_Loop* aLoop = Events_Loop::loop(); aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); @@ -382,9 +363,13 @@ bool Model_Document::finishOperation() // nothing inside in all documents, so remove this transaction from the transactions list undoInternal(true, false); } - // on finish clear redos in any case (issue 446) + // on finish clear redos in any case (issue 446) and for all subs (issue 408) myDoc->ClearRedos(); myRedos.clear(); + for (aSubIter = aSubs.begin(); aSubIter != aSubs.end(); aSubIter++) { + subDoc(*aSubIter)->myDoc->ClearRedos(); + subDoc(*aSubIter)->myRedos.clear(); + } return aResult; } @@ -413,7 +398,7 @@ void Model_Document::abortOperation() for (; aSubIter != aSubs.end(); aSubIter++) subDoc(*aSubIter)->abortOperation(); // references may be changed because they are set in attributes on the fly - synchronizeFeatures(true, true, isRoot()); + myObjs->synchronizeFeatures(true, true, isRoot()); } bool Model_Document::isOperation() const @@ -464,8 +449,11 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron subDoc(*aSubIter)->undoInternal(theWithSubs, theSynchronize); } // after redo of all sub-documents to avoid updates on not-modified data (issue 370) - if (theSynchronize) - synchronizeFeatures(true, true, isRoot()); + if (theSynchronize) { + // update the current features status + setCurrentFeature(currentFeature(false), false); + myObjs->synchronizeFeatures(true, true, isRoot()); + } } void Model_Document::undo() @@ -502,8 +490,10 @@ void Model_Document::redo() for (; aSubIter != aSubs.end(); aSubIter++) subDoc(*aSubIter)->redo(); + // update the current features status + setCurrentFeature(currentFeature(false), false); // after redo of all sub-documents to avoid updates on not-modified data (issue 370) - synchronizeFeatures(true, true, isRoot()); + myObjs->synchronizeFeatures(true, true, isRoot()); } std::list Model_Document::undoList() const @@ -537,28 +527,8 @@ void Model_Document::operationId(const std::string& theId) myTransactions.rbegin()->myId = theId; } -/// Append to the array of references a new referenced label -static void AddToRefArray(TDF_Label& theArrayLab, TDF_Label& theReferenced) -{ - Handle(TDataStd_ReferenceArray) aRefs; - if (!theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { - aRefs = TDataStd_ReferenceArray::Set(theArrayLab, 0, 0); - aRefs->SetValue(0, theReferenced); - } else { // extend array by one more element - Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(), - aRefs->Upper() + 1); - for (int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { - aNewArray->SetValue(a, aRefs->Value(a)); - } - aNewArray->SetValue(aRefs->Upper() + 1, theReferenced); - aRefs->SetInternalArray(aNewArray); - } -} - FeaturePtr Model_Document::addFeature(std::string theID) { - TDF_Label anEmptyLab; - FeaturePtr anEmptyFeature; std::shared_ptr aSession = std::dynamic_pointer_cast(ModelAPI_Session::get()); FeaturePtr aFeature = aSession->createFeature(theID, this); @@ -575,23 +545,9 @@ FeaturePtr Model_Document::addFeature(std::string theID) aDocToAdd = this; } if (aFeature) { - TDF_Label aFeatureLab; - if (!aFeature->isAction()) { // do not add action to the data model - TDF_Label aFeaturesLab = aDocToAdd->featuresLabel(); - aFeatureLab = aFeaturesLab.NewChild(); - aDocToAdd->initData(aFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS); - // keep the feature ID to restore document later correctly - TDataStd_Comment::Set(aFeatureLab, aFeature->getKind().c_str()); - aDocToAdd->myObjs.Bind(aFeatureLab, aFeature); - // store feature in the history of features array - if (aFeature->isInHistory()) { - AddToRefArray(aFeaturesLab, aFeatureLab); - } - } + aDocToAdd->myObjs->addFeature(aFeature, currentFeature(false)); if (!aFeature->isAction()) { // do not add action to the data model - // event: feature is added - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent); + setCurrentFeature(aFeature, false); // after all this feature stays in the document, so make it current } else { // feature must be executed // no creation event => updater not working, problem with remove part aFeature->execute(); @@ -600,159 +556,34 @@ FeaturePtr Model_Document::addFeature(std::string theID) return aFeature; } -/// Appenad to the array of references a new referenced label. -/// If theIndex is not -1, removes element at this index, not theReferenced. -/// \returns the index of removed element -static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, - const int theIndex = -1) -{ - int aResult = -1; // no returned - Handle(TDataStd_ReferenceArray) aRefs; - if (theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { - if (aRefs->Length() == 1) { // just erase an array - if ((theIndex == -1 && aRefs->Value(0) == theReferenced) || theIndex == 0) { - theArrayLab.ForgetAttribute(TDataStd_ReferenceArray::GetID()); - } - aResult = 0; - } else { // reduce the array - Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(), - aRefs->Upper() - 1); - int aCount = aRefs->Lower(); - for (int a = aCount; a <= aRefs->Upper(); a++, aCount++) { - if ((theIndex == -1 && aRefs->Value(a) == theReferenced) || theIndex == a) { - aCount--; - aResult = a; - } else { - aNewArray->SetValue(aCount, aRefs->Value(a)); - } - } - aRefs->SetInternalArray(aNewArray); - } - } - return aResult; -} void Model_Document::refsToFeature(FeaturePtr theFeature, - std::set >& theRefs, - const bool isSendError) + std::set >& theRefs, const bool isSendError) { - // check the feature: it must have no depended objects on it - // the dependencies can be in the feature results - std::list::const_iterator aResIter = theFeature->results().cbegin(); - for(; aResIter != theFeature->results().cend(); aResIter++) { - ResultPtr aResult = (*aResIter); - std::shared_ptr aData = - std::dynamic_pointer_cast(aResult->data()); - if (aData.get() != NULL) { - const std::set& aRefs = aData->refsToMe(); - std::set::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end(); - for(; aRefIt != aRefLast; aRefIt++) { - FeaturePtr aFeature = std::dynamic_pointer_cast((*aRefIt)->owner()); - if (aFeature.get() != NULL) - theRefs.insert(aFeature); - } - } - } - // the dependencies can be in the feature itself - std::shared_ptr aData = - std::dynamic_pointer_cast(theFeature->data()); - if (aData && !aData->refsToMe().empty()) { - const std::set& aRefs = aData->refsToMe(); - std::set::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end(); - for(; aRefIt != aRefLast; aRefIt++) { - FeaturePtr aFeature = std::dynamic_pointer_cast((*aRefIt)->owner()); - if (aFeature.get() != NULL) - theRefs.insert(aFeature); - } - } - - if (!theRefs.empty() && isSendError) { - Events_Error::send( - "Feature '" + theFeature->data()->name() + "' is used and can not be deleted"); - } + myObjs->refsToFeature(theFeature, theRefs, isSendError); } -void Model_Document::removeFeature(FeaturePtr theFeature/*, const bool theCheck*/) +void Model_Document::removeFeature(FeaturePtr theFeature) { - std::shared_ptr aData = std::static_pointer_cast(theFeature->data()); - if (aData) { - TDF_Label aFeatureLabel = aData->label().Father(); - if (myObjs.IsBound(aFeatureLabel)) - myObjs.UnBind(aFeatureLabel); - else - return; // not found feature => do not remove - - // checking that the sub-element of composite feature is removed: if yes, inform the owner - std::set > aRefs; - refsToFeature(theFeature, aRefs, false); - std::set >::iterator aRefIter = aRefs.begin(); - for(; aRefIter != aRefs.end(); aRefIter++) { - std::shared_ptr aComposite = - std::dynamic_pointer_cast(*aRefIter); - if (aComposite.get()) { - aComposite->removeFeature(theFeature); - } - } - - // erase fields - theFeature->erase(); - static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP); - // erase all attributes under the label of feature - aFeatureLabel.ForgetAllAttributes(); - // remove it from the references array - if (theFeature->isInHistory()) { - RemoveFromRefArray(featuresLabel(), aFeatureLabel); + // if this feature is current, make the current the previous feature + if (theFeature == currentFeature(false)) { + int aCurrentIndex = index(theFeature); + if (aCurrentIndex != -1) { + setCurrentFeature(std::dynamic_pointer_cast( + object(ModelAPI_Feature::group(), aCurrentIndex - 1)), false); } - // event: feature is deleted - ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group()); - // the redisplay signal should be flushed in order to erase the feature presentation in the viewer - Events_Loop::loop()->flush(EVENT_DISP); } + myObjs->removeFeature(theFeature); } -void Model_Document::addToHistory(const std::shared_ptr theObject) +void Model_Document::updateHistory(const std::shared_ptr theObject) { - TDF_Label aFeaturesLab = featuresLabel(); - std::shared_ptr aData = std::static_pointer_cast(theObject->data()); - if (!aData) { - return; // not found feature => do not remove - } - TDF_Label aFeatureLabel = aData->label().Father(); - // store feature in the history of features array - if (theObject->isInHistory()) { - AddToRefArray(aFeaturesLab, aFeatureLabel); - } else { - RemoveFromRefArray(aFeaturesLab, aFeatureLabel); - } + myObjs->updateHistory(theObject); } -FeaturePtr Model_Document::feature(TDF_Label& theLabel) const +void Model_Document::updateHistory(const std::string theGroup) { - if (myObjs.IsBound(theLabel)) - return myObjs.Find(theLabel); - return FeaturePtr(); // not found -} - -ObjectPtr Model_Document::object(TDF_Label theLabel) -{ - // try feature by label - FeaturePtr aFeature = feature(theLabel); - if (aFeature) - return feature(theLabel); - TDF_Label aFeatureLabel = theLabel.Father().Father(); // let's suppose it is result - aFeature = feature(aFeatureLabel); - if (aFeature) { - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.cbegin(); - for (; aRIter != aResults.cend(); aRIter++) { - std::shared_ptr aResData = std::dynamic_pointer_cast( - (*aRIter)->data()); - if (aResData->label().Father().IsEqual(theLabel)) - return *aRIter; - } - } - return FeaturePtr(); // not found + myObjs->updateHistory(theGroup); } std::shared_ptr Model_Document::subDocument(std::string theDocID) @@ -763,24 +594,13 @@ std::shared_ptr Model_Document::subDocument(std::string theDo const std::set Model_Document::subDocuments(const bool theActivatedOnly) const { std::set aResult; - // comment must be in any feature: it is kind - int anIndex = 0; - TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); - for (; aLabIter.More(); aLabIter.Next()) { - TDF_Label aFLabel = aLabIter.Value()->Label(); - FeaturePtr aFeature = feature(aFLabel); - if (aFeature.get()) { // if document is closed the feature may be not in myObjs map - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { - if ((*aRIter)->groupName() != ModelAPI_ResultPart::group()) continue; - if ((*aRIter)->isInHistory()) { - ResultPartPtr aPart = std::dynamic_pointer_cast(*aRIter); - if (aPart && (!theActivatedOnly || aPart->isActivated())) - aResult.insert(aPart->data()->name()); - } - } - } + std::list aPartResults; + myObjs->allResults(ModelAPI_ResultPart::group(), aPartResults); + std::list::iterator aPartRes = aPartResults.begin(); + for(; aPartRes != aPartResults.end(); aPartRes++) { + ResultPartPtr aPart = std::dynamic_pointer_cast(*aPartRes); + if (aPart && (!theActivatedOnly || aPart->isActivated())) + aResult.insert(aPart->data()->name()); } return aResult; } @@ -792,461 +612,121 @@ std::shared_ptr Model_Document::subDoc(std::string theDocID) Model_Application::getApplication()->getDocument(theDocID)); } -ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex, - const bool theHidden) +ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex) { - if (theGroupID == ModelAPI_Feature::group()) { - if (theHidden) { - int anIndex = 0; - TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); - for (; aLabIter.More(); aLabIter.Next()) { - if (theIndex == anIndex) { - TDF_Label aFLabel = aLabIter.Value()->Label(); - return feature(aFLabel); - } - anIndex++; - } - } else { - Handle(TDataStd_ReferenceArray) aRefs; - if (!featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) - return ObjectPtr(); - if (aRefs->Lower() > theIndex || aRefs->Upper() < theIndex) - return ObjectPtr(); - TDF_Label aFeatureLabel = aRefs->Value(theIndex); - return feature(aFeatureLabel); - } - } else { - // comment must be in any feature: it is kind - int anIndex = 0; - TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); - for (; aLabIter.More(); aLabIter.Next()) { - TDF_Label aFLabel = aLabIter.Value()->Label(); - FeaturePtr aFeature = feature(aFLabel); - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { - if ((*aRIter)->groupName() != theGroupID) continue; - bool isIn = theHidden && (*aRIter)->isInHistory(); - if (!isIn && (*aRIter)->isInHistory()) { // check that there is nobody references this result - isIn = !(*aRIter)->isConcealed(); - } - if (isIn) { - if (anIndex == theIndex) - return *aRIter; - anIndex++; - } - } - } - } - // not found - return ObjectPtr(); + return myObjs->object(theGroupID, theIndex); } std::shared_ptr Model_Document::objectByName( const std::string& theGroupID, const std::string& theName) { - if (theGroupID == ModelAPI_Feature::group()) { - int anIndex = 0; - TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); - for (; aLabIter.More(); aLabIter.Next()) { - TDF_Label aFLabel = aLabIter.Value()->Label(); - FeaturePtr aFeature = feature(aFLabel); - if (aFeature && aFeature->name() == theName) - return aFeature; - } - } else { - // comment must be in any feature: it is kind - int anIndex = 0; - TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); - for (; aLabIter.More(); aLabIter.Next()) { - TDF_Label aFLabel = aLabIter.Value()->Label(); - FeaturePtr aFeature = feature(aFLabel); - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { - if ((*aRIter)->groupName() == theGroupID && (*aRIter)->data()->name() == theName) - return *aRIter; - } - } - } - // not found - return ObjectPtr(); + return myObjs->objectByName(theGroupID, theName); } -int Model_Document::size(const std::string& theGroupID, const bool theHidden) +const int Model_Document::index(std::shared_ptr theObject) { - int aResult = 0; - if (theGroupID == ModelAPI_Feature::group()) { - if (theHidden) { - return myObjs.Size(); - } else { - Handle(TDataStd_ReferenceArray) aRefs; - if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) - return aRefs->Length(); - } - } else { - // comment must be in any feature: it is kind - TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); - for (; aLabIter.More(); aLabIter.Next()) { - TDF_Label aFLabel = aLabIter.Value()->Label(); - FeaturePtr aFeature = feature(aFLabel); - if (!aFeature) // may be on close - continue; - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { - if ((*aRIter)->groupName() != theGroupID) continue; - bool isIn = theHidden; - if (!isIn && (*aRIter)->isInHistory()) { // check that there is nobody references this result - isIn = !(*aRIter)->isConcealed(); - } - if (isIn) - aResult++; - } - } - } - // group is not found - return aResult; + return myObjs->index(theObject); } -TDF_Label Model_Document::featuresLabel() const +int Model_Document::size(const std::string& theGroupID) { - return myDoc->Main().FindChild(TAG_OBJECTS); + return myObjs->size(theGroupID); } -void Model_Document::setUniqueName(FeaturePtr theFeature) +std::shared_ptr Model_Document::currentFeature(const bool theVisible) { - if (!theFeature->data()->name().empty()) - return; // not needed, name is already defined - std::string aName; // result - // first count all objects of such kind to start with index = count + 1 - int aNumObjects = 0; - NCollection_DataMap::Iterator aFIter(myObjs); - for (; aFIter.More(); aFIter.Next()) { - if (aFIter.Value()->getKind() == theFeature->getKind()) - aNumObjects++; - } - // generate candidate name - std::stringstream aNameStream; - aNameStream << theFeature->getKind() << "_" << aNumObjects + 1; - aName = aNameStream.str(); - // check this is unique, if not, increase index by 1 - for (aFIter.Initialize(myObjs); aFIter.More();) { - FeaturePtr aFeature = aFIter.Value(); - bool isSameName = aFeature->data()->name() == aName; - if (!isSameName) { // check also results to avoid same results names (actual for Parts) - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { - isSameName = (*aRIter)->data()->name() == aName; + TDF_Label aRefLab = generalLabel().FindChild(TAG_CURRENT_FEATURE); + Handle(TDF_Reference) aRef; + if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) { + TDF_Label aLab = aRef->Get(); + FeaturePtr aResult = myObjs->feature(aLab); + if (theVisible) { // get nearest visible (in history) going up + while(aResult.get() && !aResult->isInHistory()) { + aResult = myObjs->nextFeature(aResult, true); } } - if (isSameName) { - aNumObjects++; - std::stringstream aNameStream; - aNameStream << theFeature->getKind() << "_" << aNumObjects + 1; - aName = aNameStream.str(); - // reinitialize iterator to make sure a new name is unique - aFIter.Initialize(myObjs); - } else - aFIter.Next(); + return aResult; } - theFeature->data()->setName(aName); + return std::shared_ptr(); // null feature means the higher than first } -void Model_Document::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag) +void Model_Document::setCurrentFeature(std::shared_ptr theCurrent, + const bool theVisible) { - std::shared_ptr aThis = Model_Application::getApplication()->getDocument( - myID); - std::shared_ptr aData(new Model_Data); - aData->setLabel(theLab.FindChild(theTag)); - aData->setObject(theObj); - theObj->setDoc(aThis); - theObj->setData(aData); - FeaturePtr aFeature = std::dynamic_pointer_cast(theObj); - if (aFeature) { - setUniqueName(aFeature); // must be before "initAttributes" because duplicate part uses name - } - theObj->initAttributes(); -} - -void Model_Document::synchronizeFeatures( - const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush) -{ - std::shared_ptr aThis = - Model_Application::getApplication()->getDocument(myID); - // after all updates, sends a message that groups of features were created or updated - Events_Loop* aLoop = Events_Loop::loop(); - static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); - static Events_ID aCreateEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); - static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); - static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); - static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); - aLoop->activateFlushes(false); - - // update all objects by checking are they on labels or not - std::set aNewFeatures, aKeptFeatures; - TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); - for (; aLabIter.More(); aLabIter.Next()) { - TDF_Label aFeatureLabel = aLabIter.Value()->Label(); - FeaturePtr aFeature; - if (!myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted - // create a feature - aFeature = std::dynamic_pointer_cast(ModelAPI_Session::get())->createFeature( - TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get()) - .ToCString(), this); - if (!aFeature) { // somethig is wrong, most probably, the opened document has invalid structure - Events_Error::send("Invalid type of object in the document"); - aLabIter.Value()->Label().ForgetAllAttributes(); - continue; - } - // this must be before "setData" to redo the sketch line correctly - myObjs.Bind(aFeatureLabel, aFeature); - aNewFeatures.insert(aFeature); - initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS); - - // event: model is updated - ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent); - } else { // nothing is changed, both iterators are incremented - aFeature = myObjs.Find(aFeatureLabel); - aKeptFeatures.insert(aFeature); - if (theMarkUpdated) { - ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent); + TDF_Label aRefLab = generalLabel().FindChild(TAG_CURRENT_FEATURE); + if (theCurrent.get()) { + if (theVisible) { // make features below which are not in history also enabled: sketch subs + FeaturePtr aNext = myObjs->nextFeature(theCurrent); + for (; aNext.get(); aNext = myObjs->nextFeature(theCurrent)) { + if (aNext->isInHistory()) { + break; // next in history is not needed + } else { // next not in history is good for making current + theCurrent = aNext; + } } } - } - // update results of the features (after features created because they may be connected, like sketch and sub elements) - std::list aComposites; // composites must be updated after their subs (issue 360) - TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID()); - for (; aLabIter2.More(); aLabIter2.Next()) { - TDF_Label aFeatureLabel = aLabIter2.Value()->Label(); - if (myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted - FeaturePtr aFeature = myObjs.Find(aFeatureLabel); - if (std::dynamic_pointer_cast(aFeature).get()) - aComposites.push_back(aFeature); - updateResults(aFeature); - } - } - std::list::iterator aComposite = aComposites.begin(); - for(; aComposite != aComposites.end(); aComposite++) { - updateResults(*aComposite); - } - - // check all features are checked: if not => it was removed - NCollection_DataMap::Iterator aFIter(myObjs); - while (aFIter.More()) { - if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end() - && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) { - FeaturePtr aFeature = aFIter.Value(); - // event: model is updated - //if (aFeature->isInHistory()) { - ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group()); - //} - // results of this feature must be redisplayed (hided) - // redisplay also removed feature (used for sketch and AISObject) - ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent); - aFeature->erase(); - // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter - myObjs.UnBind(aFIter.Key()); - // reinitialize iterator because unbind may corrupt the previous order in the map - aFIter.Initialize(myObjs); - } else - aFIter.Next(); - } - - if (theUpdateReferences) { - synchronizeBackRefs(); - } - - myExecuteFeatures = false; - aLoop->activateFlushes(true); - - if (theFlush) { - aLoop->flush(aCreateEvent); - aLoop->flush(aDeleteEvent); - aLoop->flush(anUpdateEvent); - aLoop->flush(aRedispEvent); - aLoop->flush(aToHideEvent); - } - myExecuteFeatures = true; -} + std::shared_ptr aData = std::static_pointer_cast(theCurrent->data()); + if (!aData.get()) return; // unknown case + TDF_Label aFeatureLabel = aData->label().Father(); -void Model_Document::synchronizeBackRefs() -{ - std::shared_ptr aThis = - Model_Application::getApplication()->getDocument(myID); - // keeps the concealed flags of result to catch the change and create created/deleted events - std::list > aConcealed; - // first cycle: erase all data about back-references - NCollection_DataMap::Iterator aFeatures(myObjs); - for(; aFeatures.More(); aFeatures.Next()) { - FeaturePtr aFeature = aFeatures.Value(); - std::shared_ptr aFData = - std::dynamic_pointer_cast(aFeature->data()); - if (aFData) { - aFData->eraseBackReferences(); - } - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { - std::shared_ptr aResData = - std::dynamic_pointer_cast((*aRIter)->data()); - if (aResData) { - aConcealed.push_back(std::pair(*aRIter, (*aRIter)->isConcealed())); - aResData->eraseBackReferences(); - } + Handle(TDF_Reference) aRef; + if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) { + aRef->Set(aFeatureLabel); + } else { + aRef = TDF_Reference::Set(aRefLab, aFeatureLabel); } + } else { // remove reference for the null feature + aRefLab.ForgetAttribute(TDF_Reference::GetID()); } + // make all features after this feature disabled in reversed order (to remove results without deps) + bool aPassed = false; // flag that the current object is already passed in cycle + FeaturePtr anIter = myObjs->lastFeature(); + for(; anIter.get(); anIter = myObjs->nextFeature(anIter, true)) { + // check this before passed become enabled: the current feature is enabled! + if (anIter == theCurrent) aPassed = true; + + if (anIter->setDisabled(!aPassed)) { + // state of feature is changed => so feature become updated + static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(anIter, anUpdateEvent); - // second cycle: set new back-references: only features may have reference, iterate only them - ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators(); - for(aFeatures.Initialize(myObjs); aFeatures.More(); aFeatures.Next()) { - FeaturePtr aFeature = aFeatures.Value(); - std::shared_ptr aFData = - std::dynamic_pointer_cast(aFeature->data()); - if (aFData) { - std::list > > aRefs; - aFData->referencesToObjects(aRefs); - std::list > >::iterator - aRefsIter = aRefs.begin(); - for(; aRefsIter != aRefs.end(); aRefsIter++) { - std::list::iterator aRefTo = aRefsIter->second.begin(); - for(; aRefTo != aRefsIter->second.end(); aRefTo++) { - if (*aRefTo) { - std::shared_ptr aRefData = - std::dynamic_pointer_cast((*aRefTo)->data()); - aRefData->addBackReference(aFeature, aRefsIter->first); // here the Concealed flag is updated - } - } - } - } - } - std::list >::iterator aCIter = aConcealed.begin(); - for(; aCIter != aConcealed.end(); aCIter++) { - if (aCIter->first->isConcealed() != aCIter->second) { // somethign is changed => produce event - if (aCIter->second) { // was concealed become not => creation event - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, anEvent); - } else { // was not concealed become concealed => delete event - ModelAPI_EventCreator::get()->sendDeleted(aThis, aCIter->first->groupName()); - // redisplay for the viewer (it must be disappeared also) - static Events_ID EVENT_DISP = - Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, EVENT_DISP); - } } } } -TDF_Label Model_Document::resultLabel( - const std::shared_ptr& theFeatureData, const int theResultIndex) +TDF_Label Model_Document::generalLabel() const { - const std::shared_ptr& aData = - std::dynamic_pointer_cast(theFeatureData); - return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1); -} - -void Model_Document::storeResult(std::shared_ptr theFeatureData, - std::shared_ptr theResult, - const int theResultIndex) -{ - std::shared_ptr aThis = - Model_Application::getApplication()->getDocument(myID); - theResult->setDoc(aThis); - initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS); - if (theResult->data()->name().empty()) { // if was not initialized, generate event and set a name - std::stringstream aNewName; - aNewName<name(); - if (theResultIndex > 0) // if there are several results, add unique prefix starting from second - aNewName<<"_"<data()->setName(aNewName.str()); - } + return myDoc->Main().FindChild(TAG_GENERAL); } std::shared_ptr Model_Document::createConstruction( const std::shared_ptr& theFeatureData, const int theIndex) { - TDF_Label aLab = resultLabel(theFeatureData, theIndex); - TDataStd_Comment::Set(aLab, ModelAPI_ResultConstruction::group().c_str()); - ObjectPtr anOldObject = object(aLab); - std::shared_ptr aResult; - if (anOldObject) { - aResult = std::dynamic_pointer_cast(anOldObject); - } - if (!aResult) { - aResult = std::shared_ptr(new Model_ResultConstruction); - storeResult(theFeatureData, aResult, theIndex); - } - return aResult; + return myObjs->createConstruction(theFeatureData, theIndex); } std::shared_ptr Model_Document::createBody( const std::shared_ptr& theFeatureData, const int theIndex) { - TDF_Label aLab = resultLabel(theFeatureData, theIndex); - TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str()); - ObjectPtr anOldObject = object(aLab); - std::shared_ptr aResult; - if (anOldObject) { - aResult = std::dynamic_pointer_cast(anOldObject); - } - if (!aResult) { - aResult = std::shared_ptr(new Model_ResultBody); - storeResult(theFeatureData, aResult, theIndex); - } - return aResult; + return myObjs->createBody(theFeatureData, theIndex); } std::shared_ptr Model_Document::createPart( const std::shared_ptr& theFeatureData, const int theIndex) { - TDF_Label aLab = resultLabel(theFeatureData, theIndex); - TDataStd_Comment::Set(aLab, ModelAPI_ResultPart::group().c_str()); - ObjectPtr anOldObject = object(aLab); - std::shared_ptr aResult; - if (anOldObject) { - aResult = std::dynamic_pointer_cast(anOldObject); - } - if (!aResult) { - aResult = std::shared_ptr(new Model_ResultPart); - storeResult(theFeatureData, aResult, theIndex); - } - return aResult; + return myObjs->createPart(theFeatureData, theIndex); } std::shared_ptr Model_Document::createGroup( const std::shared_ptr& theFeatureData, const int theIndex) { - TDF_Label aLab = resultLabel(theFeatureData, theIndex); - TDataStd_Comment::Set(aLab, ModelAPI_ResultGroup::group().c_str()); - ObjectPtr anOldObject = object(aLab); - std::shared_ptr aResult; - if (anOldObject) { - aResult = std::dynamic_pointer_cast(anOldObject); - } - if (!aResult) { - aResult = std::shared_ptr(new Model_ResultGroup(theFeatureData)); - storeResult(theFeatureData, aResult, theIndex); - } - return aResult; + return myObjs->createGroup(theFeatureData, theIndex); } std::shared_ptr Model_Document::createParameter( const std::shared_ptr& theFeatureData, const int theIndex) { - TDF_Label aLab = resultLabel(theFeatureData, theIndex); - TDataStd_Comment::Set(aLab, ModelAPI_ResultParameter::group().c_str()); - ObjectPtr anOldObject = object(aLab); - std::shared_ptr aResult; - if (anOldObject) { - aResult = std::dynamic_pointer_cast(anOldObject); - } - if (!aResult) { - aResult = std::shared_ptr(new Model_ResultParameter); - storeResult(theFeatureData, aResult, theIndex); - } - return aResult; + return myObjs->createParameter(theFeatureData, theIndex); } std::shared_ptr Model_Document::feature( @@ -1255,68 +735,11 @@ std::shared_ptr Model_Document::feature( std::shared_ptr aData = std::dynamic_pointer_cast(theResult->data()); if (aData) { TDF_Label aFeatureLab = aData->label().Father().Father().Father(); - return feature(aFeatureLab); + return myObjs->feature(aFeatureLab); } return FeaturePtr(); } -void Model_Document::updateResults(FeaturePtr theFeature) -{ - // for not persistent is will be done by parametric updater automatically - //if (!theFeature->isPersistentResult()) return; - // check the existing results and remove them if there is nothing on the label - std::list::const_iterator aResIter = theFeature->results().cbegin(); - while(aResIter != theFeature->results().cend()) { - ResultPtr aBody = std::dynamic_pointer_cast(*aResIter); - if (aBody) { - if (!aBody->data()->isValid()) { - // found a disappeared result => remove it - theFeature->removeResult(aBody); - // start iterate from beginning because iterator is corrupted by removing - aResIter = theFeature->results().cbegin(); - continue; - } - } - aResIter++; - } - // it may be on undo - if (!theFeature->data() || !theFeature->data()->isValid()) - return; - // check that results are presented on all labels - int aResSize = theFeature->results().size(); - TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father()); - for(; aLabIter.More(); aLabIter.Next()) { - // here must be GUID of the feature - int aResIndex = aLabIter.Value().Tag() - 1; - ResultPtr aNewBody; - if (aResSize <= aResIndex) { - TDF_Label anArgLab = aLabIter.Value(); - Handle(TDataStd_Comment) aGroup; - if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) { - if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) { - aNewBody = createBody(theFeature->data(), aResIndex); - } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) { - aNewBody = createPart(theFeature->data(), aResIndex); - } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) { - theFeature->execute(); // construction shapes are needed for sketch solver - break; - } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) { - aNewBody = createGroup(theFeature->data(), aResIndex); - } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) { - theFeature->attributeChanged("expression"); // just produce a value - break; - } else { - Events_Error::send(std::string("Unknown type of result is found in the document:") + - TCollection_AsciiString(aGroup->Get()).ToCString()); - } - } - if (aNewBody) { - theFeature->setResult(aNewBody, aResIndex); - } - } - } -} - Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper) { return TDF_LabelMapHasher::HashCode(theLab, theUpper); @@ -1342,20 +765,5 @@ TDF_Label Model_Document::findNamingName(std::string theName) ResultPtr Model_Document::findByName(const std::string theName) { - NCollection_DataMap::Iterator anObjIter(myObjs); - for(; anObjIter.More(); anObjIter.Next()) { - FeaturePtr& aFeature = anObjIter.ChangeValue(); - if (!aFeature) // may be on close - continue; - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { - if (aRIter->get() && (*aRIter)->data() && (*aRIter)->data()->isValid() && - (*aRIter)->data()->name() == theName) { - return *aRIter; - } - } - } - // not found - return ResultPtr(); + return myObjs->findByName(theName); }