From: mpv Date: Mon, 18 May 2015 07:21:26 +0000 (+0300) Subject: Make features history working. Optimization of features and results management and... X-Git-Tag: V_1.2.0~153 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=96912644cf6607688466ac69f1f098fd2fff37b7;p=modules%2Fshaper.git Make features history working. Optimization of features and results management and access. Appending feature into the arbitrary position of the features list. --- diff --git a/src/Model/CMakeLists.txt b/src/Model/CMakeLists.txt index eef87c35f..46c9881a2 100644 --- a/src/Model/CMakeLists.txt +++ b/src/Model/CMakeLists.txt @@ -6,6 +6,7 @@ SET(PROJECT_HEADERS Model.h Model_Application.h Model_Document.h + Model_Objects.h Model_Session.h Model_Data.h Model_AttributeDouble.h @@ -33,6 +34,7 @@ SET(PROJECT_HEADERS SET(PROJECT_SOURCES Model_Application.cpp Model_Document.cpp + Model_Objects.cpp Model_Session.cpp Model_Data.cpp Model_AttributeDouble.cpp diff --git a/src/Model/Model_Application.cpp b/src/Model/Model_Application.cpp index 212fd4c9c..60bf41d9f 100644 --- a/src/Model/Model_Application.cpp +++ b/src/Model/Model_Application.cpp @@ -33,6 +33,7 @@ const std::shared_ptr& Model_Application::getDocument(string the bool isRoot = theDocID == "root"; // the document is root std::shared_ptr aNew( new Model_Document(theDocID, isRoot ? thePartSetKind : thePartKind)); + aNew->setThis(aNew); myDocs[theDocID] = aNew; // load it if it must be loaded by demand diff --git a/src/Model/Model_AttributeRefAttr.cpp b/src/Model/Model_AttributeRefAttr.cpp index 38e989e04..f399ba5be 100644 --- a/src/Model/Model_AttributeRefAttr.cpp +++ b/src/Model/Model_AttributeRefAttr.cpp @@ -7,6 +7,7 @@ #include "Model_AttributeRefAttr.h" #include "Model_Application.h" #include "Model_Data.h" +#include "Model_Objects.h" #include using namespace std; @@ -76,7 +77,7 @@ ObjectPtr Model_AttributeRefAttr::object() owner()->document()); if (aDoc) { TDF_Label aRefLab = myRef->Get(); - return aDoc->object(aRefLab); + return aDoc->objects()->object(aRefLab); } } // not initialized diff --git a/src/Model/Model_AttributeRefList.cpp b/src/Model/Model_AttributeRefList.cpp index b1fcda046..3e4f5a21d 100644 --- a/src/Model/Model_AttributeRefList.cpp +++ b/src/Model/Model_AttributeRefList.cpp @@ -7,6 +7,7 @@ #include "Model_AttributeRefList.h" #include "Model_Application.h" #include "Model_Data.h" +#include "Model_Objects.h" #include #include @@ -37,7 +38,7 @@ void Model_AttributeRefList::remove(ObjectPtr theObject) if (aDoc) { const TDF_LabelList& aList = myRef->List(); for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { - ObjectPtr anObj = aDoc->object(aLIter.Value()); + ObjectPtr anObj = aDoc->objects()->object(aLIter.Value()); if (anObj.get() == NULL) { myRef->Remove(aLIter.Value()); REMOVE_BACK_REF(theObject); @@ -70,7 +71,7 @@ list Model_AttributeRefList::list() if (aDoc) { const TDF_LabelList& aList = myRef->List(); for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { - ObjectPtr anObj = aDoc->object(aLIter.Value()); + ObjectPtr anObj = aDoc->objects()->object(aLIter.Value()); aResult.push_back(anObj); } } @@ -86,7 +87,7 @@ ObjectPtr Model_AttributeRefList::object(const int theIndex) const int anIndex = 0; for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next(), anIndex++) { if (anIndex == theIndex) - return aDoc->object(aLIter.Value()); + return aDoc->objects()->object(aLIter.Value()); } } return ObjectPtr(); diff --git a/src/Model/Model_AttributeReference.cpp b/src/Model/Model_AttributeReference.cpp index 9c51e545b..011c8bfbc 100644 --- a/src/Model/Model_AttributeReference.cpp +++ b/src/Model/Model_AttributeReference.cpp @@ -8,6 +8,7 @@ #include "Model_Application.h" #include "Model_Events.h" #include "Model_Data.h" +#include "Model_Objects.h" #include #include @@ -64,9 +65,9 @@ ObjectPtr Model_AttributeReference::value() if (myRef->Label().FindAttribute(TDataStd_AsciiString::GetID(), anEntry)) { std::shared_ptr aDR = std::dynamic_pointer_cast(aRefDoc); TDF_Label aRefLab; - TDF_Tool::Label(aDR->featuresLabel().Data(), anEntry->Get().ToCString(), aRefLab); + TDF_Tool::Label(aDR->objects()->featuresLabel().Data(), anEntry->Get().ToCString(), aRefLab); if (!aRefLab.IsNull()) { - return aDR->object(aRefLab); + return aDR->objects()->object(aRefLab); } } } @@ -76,7 +77,7 @@ ObjectPtr Model_AttributeReference::value() if (aDoc) { TDF_Label aRefLab = myRef->Get(); if (!aRefLab.IsNull()) { // it may happen with old document, issue #285 - return aDoc->object(aRefLab); + return aDoc->objects()->object(aRefLab); } } } diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index 4e96a5be5..b65974b14 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -62,6 +62,7 @@ class Model_Data : public ModelAPI_Data } friend class Model_Document; + friend class Model_Objects; friend class Model_Update; friend class Model_AttributeReference; friend class Model_AttributeRefAttr; diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 108bb398e..df8c90c79 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,25 +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) // 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) -// 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 - 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; @@ -75,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) { @@ -171,7 +163,10 @@ 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); + DocumentPtr aThis = myObjs->owner(); + delete myObjs; + myObjs = new Model_Objects(myDoc->Main()); // synchronisation is inside + myObjs->setOwner(aThis); aSession->setCheckTransactions(true); aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false); aSession->setActiveDocument(anApp->getDocument(myID), true); @@ -266,33 +261,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); @@ -341,7 +317,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)); @@ -420,7 +396,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 @@ -472,7 +448,7 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron } // after redo of all sub-documents to avoid updates on not-modified data (issue 370) if (theSynchronize) - synchronizeFeatures(true, true, isRoot()); + myObjs->synchronizeFeatures(true, true, isRoot()); } void Model_Document::undo() @@ -510,7 +486,7 @@ void Model_Document::redo() subDoc(*aSubIter)->redo(); // 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 @@ -544,28 +520,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); @@ -582,24 +538,8 @@ 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); - aFeature->setDisabled(false); // by default created feature is enabled 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 @@ -609,167 +549,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); - } - } - // 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); - } - } - - // 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); - } -} - -FeaturePtr Model_Document::feature(TDF_Label& theLabel) const -{ - if (myObjs.IsBound(theLabel)) - return myObjs.Find(theLabel); - return FeaturePtr(); // not found + myObjs->updateHistory(theObject); } -ObjectPtr Model_Document::object(TDF_Label theLabel) +void Model_Document::updateHistory(const std::string theGroup) { - // 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) @@ -780,24 +587,12 @@ 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()); - } - } - } + int aNum = myObjs->size(ModelAPI_ResultPart::group()); + for(int a = 0; a < aNum; a++) { + ResultPartPtr aPart = std::dynamic_pointer_cast( + myObjs->object(ModelAPI_ResultPart::group(), a)); + if (aPart && (!theActivatedOnly || aPart->isActivated())) + aResult.insert(aPart->data()->name()); } return aResult; } @@ -809,160 +604,25 @@ 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); } const int Model_Document::index(std::shared_ptr theObject) { - const std::string aGroupName = theObject->groupName(); - if (aGroupName == 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 == theObject) - return anIndex; - if (aFeature->isInHistory()) - anIndex++; - } - } 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 == theObject) - return anIndex; - if ((*aRIter)->groupName() == aGroupName) { - bool isIn = (*aRIter)->isInHistory() && !(*aRIter)->isConcealed(); - if (isIn) { - anIndex++; - } - } - } - } - } - // not found - return -1; + return myObjs->index(theObject); } -int Model_Document::size(const std::string& theGroupID, const bool theHidden) +int Model_Document::size(const std::string& theGroupID) { - 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->size(theGroupID); } std::shared_ptr Model_Document::currentFeature(const bool theVisible) @@ -971,16 +631,11 @@ std::shared_ptr Model_Document::currentFeature(const bool theV Handle(TDF_Reference) aRef; if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) { TDF_Label aLab = aRef->Get(); - FeaturePtr aResult = feature(aLab); + FeaturePtr aResult = myObjs->feature(aLab); if (theVisible) { // get nearest visible (in history) going up - int aTag = aLab.Tag(); - while(aTag > 1 && (!aResult.get() || !aResult->isInHistory())) { - aTag--; - aLab = aLab.Father().FindChild(aTag); - aResult = feature(aLab); + while(aResult.get() && !aResult->isInHistory()) { + aResult = myObjs->nextFeature(aResult, true); } - if (aTag <= 1) - aResult.reset(); } return aResult; } @@ -992,402 +647,78 @@ void Model_Document::setCurrentFeature(std::shared_ptr theCurr { TDF_Label aRefLab = generalLabel().FindChild(TAG_CURRENT_FEATURE); if (theCurrent.get()) { - std::shared_ptr aData = std::static_pointer_cast(theCurrent->data()); - if (aData.get()) { - TDF_Label aFeatureLabel = aData->label().Father(); - if (theVisible) { // make features below which are not in history also enabled: sketch subs - int aTag = aFeatureLabel.Tag(); - FeaturePtr aNextFeature; - TDF_Label aNextLabel; - for(aTag++; true; aTag++) { - TDF_Label aLabel = aFeatureLabel.Father().FindChild(aTag, 0); - if (aLabel.IsNull()) - break; - FeaturePtr aFeature = feature(aLabel); - if (aFeature.get()) { - if (aFeature->isInHistory()) - break; - aNextFeature = aFeature; - aNextLabel = aLabel; - } + 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; } - if (aNextFeature.get()) { - theCurrent = aNextFeature; - aFeatureLabel = aNextLabel; - } - } - Handle(TDF_Reference) aRef; - if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) { - aRef->Set(aFeatureLabel); - } else { - aRef = TDF_Reference::Set(aRefLab, aFeatureLabel); } } + std::shared_ptr aData = std::static_pointer_cast(theCurrent->data()); + if (!aData.get()) return; // unknown case + TDF_Label aFeatureLabel = aData->label().Father(); + + 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 - int aSize = size(ModelAPI_Feature::group(), true); - for(int a = aSize - 1; a >= 0; a--) { - FeaturePtr aFeature = - std::dynamic_pointer_cast(object(ModelAPI_Feature::group(), a, true)); - + FeaturePtr anIter = myObjs->lastFeature(); + for(; anIter.get(); anIter = myObjs->nextFeature(anIter, true)) { // check this before passed become enabled: the current feature is enabled! - if (aFeature == theCurrent) aPassed = true; + if (anIter == theCurrent) aPassed = true; - if (aFeature->setDisabled(!aPassed)) { + 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(aFeature, anUpdateEvent); + ModelAPI_EventCreator::get()->sendUpdated(anIter, anUpdateEvent); } } } -TDF_Label Model_Document::featuresLabel() const -{ - return myDoc->Main().FindChild(TAG_OBJECTS); -} - TDF_Label Model_Document::generalLabel() const { return myDoc->Main().FindChild(TAG_GENERAL); } -void Model_Document::setUniqueName(FeaturePtr theFeature) -{ - 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; - } - } - 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(); - } - theFeature->data()->setName(aName); -} - -void Model_Document::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag) -{ - 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); - } - } - } - // 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; -} - -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(); - } - } - } - - // 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) -{ - 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()); - } -} - 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( @@ -1396,68 +727,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); @@ -1483,20 +757,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); } diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index f190c55df..07a899ea8 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -14,16 +14,11 @@ #include #include -#include -#include #include #include class Handle_Model_Document; - -// for TDF_Label map usage -static Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper); -static Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2); +class Model_Objects; /**\class Model_Document * \ingroup DataModel @@ -91,14 +86,6 @@ class Model_Document : public ModelAPI_Document //! \param theFeature a removed feature MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature); - //! Returns the existing feature by the label - //! \param theLabel base label of the feature - MODEL_EXPORT virtual FeaturePtr feature(TDF_Label& theLabel) const; - - //! Returns the existing object: result or feature - //! \param theLabel base label of the object - MODEL_EXPORT virtual ObjectPtr object(TDF_Label theLabel); - //! Returns the first found object in the group by the object name //! \param theGroupID group that contains an object //! \param theName name of the object to search @@ -126,13 +113,10 @@ class Model_Document : public ModelAPI_Document //! Returns the feature in the group by the index (started from zero) //! \param theGroupID group that contains a feature //! \param theIndex zero-based index of feature in the group - //! \param theHidden if it is true, it counts also the features that are not in tree - MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex, - const bool theHidden = false); + MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex); //! Returns the number of features in the group - //! If theHidden is true, it counts also the features that are not in tree - MODEL_EXPORT virtual int size(const std::string& theGroupID, const bool theHidden = false); + MODEL_EXPORT virtual int size(const std::string& theGroupID); //! Returns the feature that is currently edited in this document, normally //! this is the latest created feature @@ -169,7 +153,7 @@ class Model_Document : public ModelAPI_Document ///! Returns true if parametric updater need to execute feature on recomputartion ///! On abort, undo or redo it is not necessary: results in document are updated automatically - bool executeFeatures() {return myExecuteFeatures;} + bool& executeFeatures() {return myExecuteFeatures;} //! Registers the name of the shape for the topological naming needs void addNamingName(const TDF_Label theLabel, std::string theName); @@ -180,25 +164,9 @@ class Model_Document : public ModelAPI_Document ResultPtr findByName(const std::string theName); protected: - - //! Returns (creates if needed) the features label - TDF_Label featuresLabel() const; //! Returns (creates if needed) the general label TDF_Label generalLabel() const; - //! Initializes feature with a unique name in this group (unique name is generated as - //! feature type + "_" + index - void setUniqueName(FeaturePtr theFeature); - - //! Synchronizes myFeatures list with the updated document - //! \param theMarkUpdated causes the "update" event for all features - //! \param theUpdateReferences causes the update of back-references - //! \param theFlush makes flush all events in the end of all modifications of this method - void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences, - const bool theFlush); - //! Synchronizes the BackReferences list in Data of Features and Results - void synchronizeBackRefs(); - //! Creates new document with binary file format Model_Document(const std::string theID, const std::string theKind); @@ -212,20 +180,6 @@ class Model_Document : public ModelAPI_Document //! \returns true if resulting transaction is not empty and can be undoed void compactNested(); - //! Initializes the data fields of the feature - void initData(ObjectPtr theObj, TDF_Label theLab, const int theTag); - - //! Allows to store the result in the data tree of the document (attaches 'data' of result to tree) - MODEL_EXPORT virtual void storeResult(std::shared_ptr theFeatureData, - std::shared_ptr theResult, - const int theResultIndex = 0); - - //! returns the label of result by index; creates this label if it was not created before - TDF_Label resultLabel(const std::shared_ptr& theFeatureData, const int theResultIndex); - - //! Updates the results list of the feature basing on the current data tree - void updateResults(FeaturePtr theFeature); - //! Returns all sub documents const std::set subDocuments(const bool theActivatedOnly) const; @@ -242,15 +196,25 @@ class Model_Document : public ModelAPI_Document std::list redoList() const; /// Internally makes document know that feature was removed or added in history after creation - MODEL_EXPORT virtual void addToHistory(const std::shared_ptr theObject); + virtual void updateHistory(const std::shared_ptr theObject); + /// Internally makes document know that feature was removed or added in history after creation + virtual void updateHistory(const std::string theGroup); /// Returns true if the document is root module document bool isRoot() const; + /// Sets shared pointer to this + void setThis(DocumentPtr theDoc); + + /// Returns the objects manager + Model_Objects* objects() {return myObjs;} + friend class Model_Application; friend class Model_Session; friend class Model_Update; friend class Model_AttributeReference; + friend class Model_AttributeRefAttr; + friend class Model_AttributeRefList; friend class DFBrowser; private: @@ -258,6 +222,8 @@ class Model_Document : public ModelAPI_Document std::string myKind; ///< kind of the document in the application Handle_TDocStd_Document myDoc; ///< OCAF document + Model_Objects *myObjs; ///< data manager of this document + /// counter value of transaction on the last "save" call, used for "IsModified" method int myTransactionSave; /// number of nested transactions performed (list becasue may be nested inside of nested) @@ -277,9 +243,7 @@ class Model_Document : public ModelAPI_Document std::list myTransactions; /// list of info about transactions undone (first is oldest undone) std::list myRedos; - /// All features managed by this document (not only in history of OB) - /// For optimization mapped by labels - NCollection_DataMap myObjs; + /// Optimization for finding the shape-label by topological naming names std::map myNamingNames; /// If it is true, features are not executed on update (on abort, undo, redo) diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp new file mode 100644 index 000000000..5e5151bcf --- /dev/null +++ b/src/Model/Model_Objects.cpp @@ -0,0 +1,839 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: Model_Objects.cxx +// Created: 15 May 2015 +// Author: Mikhail PONIKAROV + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, results) + +// 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 + +Model_Objects::Model_Objects(TDF_Label theMainLab) : myMain(theMainLab) +{ + // update all fields and recreate features and result objects if needed + synchronizeFeatures(false, true, true); +} + +Model_Objects::~Model_Objects() +{ + // delete all features of this document + Events_Loop* aLoop = Events_Loop::loop(); + NCollection_DataMap::Iterator aFeaturesIter(myFeatures); + for(; aFeaturesIter.More(); aFeaturesIter.Next()) { + FeaturePtr aFeature = aFeaturesIter.Value(); + static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Feature::group()); + ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP); + aFeature->eraseResults(); + aFeature->erase(); + } + myFeatures.Clear(); + aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED)); + aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + +} + +/// Appends to the array of references a new referenced label +static void AddToRefArray(TDF_Label& theArrayLab, TDF_Label& theReferenced, TDF_Label& thePrevLab) +{ + 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); + int aPassedPrev = 0; // prev feature is found and passed + if (thePrevLab.IsNull()) { // null means that inserted feature must be the first + aNewArray->SetValue(aRefs->Lower(), theReferenced); + aPassedPrev = 1; + } + for (int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { + aNewArray->SetValue(a + aPassedPrev, aRefs->Value(a)); + if (!aPassedPrev && aRefs->Value(a).IsEqual(thePrevLab)) { + aPassedPrev = 1; + aNewArray->SetValue(a + 1, theReferenced); + } + } + if (!aPassedPrev) // not found: unknown situation + aNewArray->SetValue(aRefs->Upper() + 1, theReferenced); + aRefs->SetInternalArray(aNewArray); + } +} + +void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterThis) +{ + if (!theFeature->isAction()) { // do not add action to the data model + TDF_Label aFeaturesLab = featuresLabel(); + TDF_Label aFeatureLab = aFeaturesLab.NewChild(); + initData(theFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS); + // keep the feature ID to restore document later correctly + TDataStd_Comment::Set(aFeatureLab, theFeature->getKind().c_str()); + myFeatures.Bind(aFeatureLab, theFeature); + // store feature in the features array + TDF_Label aPrevFeateureLab; + if (theAfterThis.get()) { // searching for the previous feature label + std::shared_ptr aPrevData = + std::dynamic_pointer_cast(theAfterThis->data()); + if (aPrevData.get()) { + aPrevFeateureLab = aPrevData->label().Father(); + } + } + AddToRefArray(aFeaturesLab, aFeatureLab, aPrevFeateureLab); + // event: feature is added + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); + ModelAPI_EventCreator::get()->sendUpdated(theFeature, anEvent); + theFeature->setDisabled(false); // by default created feature is enabled + updateHistory(ModelAPI_Feature::group()); + } +} + +/// Appends 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_Objects::refsToFeature(FeaturePtr theFeature, + 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"); + } +} + +void Model_Objects::removeFeature(FeaturePtr theFeature) +{ + std::shared_ptr aData = std::static_pointer_cast(theFeature->data()); + if (aData) { + TDF_Label aFeatureLabel = aData->label().Father(); + if (myFeatures.IsBound(aFeatureLabel)) + myFeatures.UnBind(aFeatureLabel); + else + return; // not found feature => do not remove + + clearHistory(theFeature); + // 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); + } + // 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); + updateHistory(ModelAPI_Feature::group()); + } +} + +void Model_Objects::clearHistory(ObjectPtr theObj) +{ + if (theObj) { + const std::string aGroup = theObj->groupName(); + std::map >::iterator aHIter = myHistory.find(aGroup); + if (aHIter != myHistory.end()) + myHistory.erase(aHIter); // erase from map => this means that it is not synchronized + if (theObj->groupName() == ModelAPI_Feature::group()) { // clear results group of the feature + FeaturePtr aFeature = std::dynamic_pointer_cast(theObj); + if (aFeature->firstResult().get()) + clearHistory(aFeature->firstResult()); + } + } +} + +void Model_Objects::createHistory(const std::string& theGroupID) +{ + std::map >::iterator aHIter = myHistory.find(theGroupID); + if (aHIter == myHistory.end()) { + myHistory[theGroupID] = std::vector(); + std::vector& aResult = myHistory[theGroupID]; + // iterate the array of references and get feature by feature from the array + bool isFeature = theGroupID == ModelAPI_Feature::group(); + Handle(TDataStd_ReferenceArray) aRefs; + if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { + for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { + FeaturePtr aFeature = feature(aRefs->Value(a)); + if (aFeature.get()) { + if (isFeature) { // here may be also disabled features + if (aFeature->isInHistory()) { + aResult.push_back(aFeature); + } + } else if (!aFeature->isDisabled()) { // iterate all results of not-disabled feature + const std::list >& aResults = aFeature->results(); + std::list >::const_iterator aRIter = aResults.begin(); + for (; aRIter != aResults.cend(); aRIter++) { + ResultPtr aRes = *aRIter; + if (aRes->groupName() != theGroupID) break; // feature have only same group results + if (!aRes->isDisabled() && aRes->isInHistory() && !aRes->isConcealed()) { + aResult.push_back(*aRIter); + } + } + } + } + } + } + } +} + +void Model_Objects::updateHistory(const std::shared_ptr theObject) +{ + clearHistory(theObject); +} + +void Model_Objects::updateHistory(const std::string theGroup) +{ + std::map >::iterator aHIter = myHistory.find(theGroup); + if (aHIter != myHistory.end()) + myHistory.erase(aHIter); // erase from map => this means that it is not synchronized +} + +FeaturePtr Model_Objects::feature(TDF_Label& theLabel) const +{ + if (myFeatures.IsBound(theLabel)) + return myFeatures.Find(theLabel); + return FeaturePtr(); // not found +} + +ObjectPtr Model_Objects::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 +} + +ObjectPtr Model_Objects::object(const std::string& theGroupID, const int theIndex) +{ + createHistory(theGroupID); + return myHistory[theGroupID][theIndex]; +} + +std::shared_ptr Model_Objects::objectByName( + const std::string& theGroupID, const std::string& theName) +{ + createHistory(theGroupID); + std::vector& allObjs = myHistory[theGroupID]; + std::vector::iterator anObjIter = allObjs.begin(); + for(; anObjIter != allObjs.end(); anObjIter++) { + if ((*anObjIter)->data()->name() == theName) + return *anObjIter; + } + // not found + return ObjectPtr(); +} + +const int Model_Objects::index(std::shared_ptr theObject) +{ + std::string aGroup = theObject->groupName(); + createHistory(aGroup); + std::vector& allObjs = myHistory[aGroup]; + std::vector::iterator anObjIter = allObjs.begin(); // iterate to search object + for(int anIndex = 0; anObjIter != allObjs.end(); anObjIter++, anIndex++) { + if ((*anObjIter) == theObject) + return anIndex; + } + // not found + return -1; +} + +int Model_Objects::size(const std::string& theGroupID) +{ + createHistory(theGroupID); + return myHistory[theGroupID].size(); +} + +TDF_Label Model_Objects::featuresLabel() const +{ + return myMain.FindChild(TAG_OBJECTS); +} + +void Model_Objects::setUniqueName(FeaturePtr theFeature) +{ + if (!theFeature->data()->name().empty()) + return; // not needed, name is already defined + std::string aName; // result + // first count all features of such kind to start with index = count + 1 + int aNumObjects = 0; + NCollection_DataMap::Iterator aFIter(myFeatures); + 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(myFeatures); 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; + } + } + 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(myFeatures); + } else + aFIter.Next(); + } + theFeature->data()->setName(aName); +} + +void Model_Objects::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag) +{ + std::shared_ptr aData(new Model_Data); + aData->setLabel(theLab.FindChild(theTag)); + aData->setObject(theObj); + theObj->setDoc(myDoc); + 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_Objects::synchronizeFeatures( + const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush) +{ + Model_Document* anOwner = std::dynamic_pointer_cast(myDoc).get(); + if (!anOwner) // this may happen on creation of document: nothing there, so nothing to synchronize + return; + // 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 (!myFeatures.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(), anOwner); + 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 + myFeatures.Bind(aFeatureLabel, aFeature); + aNewFeatures.insert(aFeature); + initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS); + updateHistory(aFeature); + + // event: model is updated + ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent); + } else { // nothing is changed, both iterators are incremented + aFeature = myFeatures.Find(aFeatureLabel); + aKeptFeatures.insert(aFeature); + if (theMarkUpdated) { + ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent); + } + } + } + // 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 (myFeatures.IsBound(aFeatureLabel)) { // a new feature is inserted + FeaturePtr aFeature = myFeatures.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(myFeatures); + 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(myDoc, 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); + updateHistory(aFeature); + aFeature->erase(); + // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter + myFeatures.UnBind(aFIter.Key()); + // reinitialize iterator because unbind may corrupt the previous order in the map + aFIter.Initialize(myFeatures); + } else + aFIter.Next(); + } + + if (theUpdateReferences) { + synchronizeBackRefs(); + } + if (theMarkUpdated) { // this means there is no control what was modified => remove history cash + myHistory.clear(); + } + + anOwner->executeFeatures() = false; + aLoop->activateFlushes(true); + + if (theFlush) { + aLoop->flush(aCreateEvent); + aLoop->flush(aDeleteEvent); + aLoop->flush(anUpdateEvent); + aLoop->flush(aRedispEvent); + aLoop->flush(aToHideEvent); + } + anOwner->executeFeatures() = true; +} + +void Model_Objects::synchronizeBackRefs() +{ + // 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(myFeatures); + 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(); + } + } + } + + // second cycle: set new back-references: only features may have reference, iterate only them + ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators(); + for(aFeatures.Initialize(myFeatures); 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(myDoc, 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_Objects::resultLabel( + const std::shared_ptr& theFeatureData, const int theResultIndex) +{ + const std::shared_ptr& aData = + std::dynamic_pointer_cast(theFeatureData); + return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1); +} + +void Model_Objects::storeResult(std::shared_ptr theFeatureData, + std::shared_ptr theResult, + const int theResultIndex) +{ + theResult->setDoc(myDoc); + 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()); + } +} + +std::shared_ptr Model_Objects::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; +} + +std::shared_ptr Model_Objects::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; +} + +std::shared_ptr Model_Objects::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; +} + +std::shared_ptr Model_Objects::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; +} + +std::shared_ptr Model_Objects::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; +} + +std::shared_ptr Model_Objects::feature( + const std::shared_ptr& theResult) +{ + std::shared_ptr aData = std::dynamic_pointer_cast(theResult->data()); + if (aData) { + TDF_Label aFeatureLab = aData->label().Father().Father().Father(); + return feature(aFeatureLab); + } + return FeaturePtr(); +} + +void Model_Objects::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); + } + } + } +} + +ResultPtr Model_Objects::findByName(const std::string theName) +{ + NCollection_DataMap::Iterator anObjIter(myFeatures); + for(; anObjIter.More(); anObjIter.Next()) { + FeaturePtr& aFeature = anObjIter.ChangeValue(); + if (!aFeature.get() || aFeature->isDisabled()) // may be on close + continue; + const std::list >& aResults = aFeature->results(); + std::list >::const_iterator aRIter = aResults.begin(); + for (; aRIter != aResults.cend(); aRIter++) { + ResultPtr aRes = *aRIter; + if (aRes.get() && aRes->data() && aRes->data()->isValid() && !aRes->isDisabled() && + aRes->data()->name() == theName) { + return aRes; + } + } + } + // not found + return ResultPtr(); +} + +FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theReverse) +{ + std::shared_ptr aData = std::static_pointer_cast(theCurrent->data()); + if (aData) { + TDF_Label aFeatureLabel = aData->label().Father(); + Handle(TDataStd_ReferenceArray) aRefs; + if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { + for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { // iterate all existing features + if (aRefs->Value(a).IsEqual(aFeatureLabel)) { + a += theReverse ? -1 : 1; + if (a >= aRefs->Lower() && a <= aRefs->Upper()) + return feature(aRefs->Value(a)); + break; // finish iiteration: it's last feature + } + } + } + } + return FeaturePtr(); // not found, last, or something is wrong +} + +FeaturePtr Model_Objects::firstFeature() +{ + Handle(TDataStd_ReferenceArray) aRefs; + if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { + return feature(aRefs->Value(aRefs->Lower())); + } + return FeaturePtr(); // no features at all +} + +FeaturePtr Model_Objects::lastFeature() +{ + Handle(TDataStd_ReferenceArray) aRefs; + if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { + return feature(aRefs->Value(aRefs->Upper())); + } + return FeaturePtr(); // no features at all +} + +Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper) +{ + return TDF_LabelMapHasher::HashCode(theLab, theUpper); + +} +Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2) +{ + return TDF_LabelMapHasher::IsEqual(theLab1, theLab2); +} diff --git a/src/Model/Model_Objects.h b/src/Model/Model_Objects.h new file mode 100644 index 000000000..bf9b2bace --- /dev/null +++ b/src/Model/Model_Objects.h @@ -0,0 +1,191 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: Model_Objects.h +// Created: 15 May 2015 +// Author: Mikhail PONIKAROV + +#ifndef Model_Objects_H_ +#define Model_Objects_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// for TDF_Label map usage +static Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper); +static Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2); + +/**\class Model_Objects + * \ingroup DataModel + * \brief Manager of objects of the document. Normally one this class corresponds to + * one document and just helper to manage objects (ModelAPI_Objects) inside of the document + * on the level of data storage. + */ +class Model_Objects +{ + public: + //! Registers the fieature in the data structure + //! \param theFeature feature that must be added to the data structure + //! \param theAfterThis the feature will be added after this feature; + //! if it is null, the added feature will be the first + void addFeature(FeaturePtr theFeature, const FeaturePtr theAfterThis); + + //! Return a list of features, which refers to the feature + //! \param theFeature a feature + //! \param theRefs a list of reference features + //! \param isSendError a flag whether the error message should be send + void refsToFeature(FeaturePtr theFeature, + std::set& theRefs, + const bool isSendError = true); + + //! Removes the feature from the document (with result) + //! \param theFeature a removed feature + void removeFeature(FeaturePtr theFeature); + + //! Returns the existing feature by the label + //! \param theLabel base label of the feature + FeaturePtr feature(TDF_Label& theLabel) const; + + //! Returns the existing object: result or feature + //! \param theLabel base label of the object + ObjectPtr object(TDF_Label theLabel); + + //! Returns the first found object in the group by the object name + //! \param theGroupID group that contains an object + //! \param theName name of the object to search + //! \returns null if such object is not found + std::shared_ptr objectByName( + const std::string& theGroupID, const std::string& theName); + + //! Returns the result by the result name + ResultPtr Model_Objects::findByName(const std::string theName); + + + //! Returns the object index in the group. Object must be visible. Otherwise returns -1. + //! \param theObject object of this document + //! \returns index started from zero, or -1 if object is invisible or belongs to another document + const int index(std::shared_ptr theObject); + + //! Returns the feature in the group by the index (started from zero) + //! \param theGroupID group that contains a feature + //! \param theIndex zero-based index of feature in the group + ObjectPtr object(const std::string& theGroupID, const int theIndex); + + //! Returns the number of features in the group + int size(const std::string& theGroupID); + + /// Creates a construction cresults + std::shared_ptr createConstruction( + const std::shared_ptr& theFeatureData, const int theIndex = 0); + /// Creates a body results + std::shared_ptr createBody( + const std::shared_ptr& theFeatureData, const int theIndex = 0); + /// Creates a part results + std::shared_ptr createPart( + const std::shared_ptr& theFeatureData, const int theIndex = 0); + /// Creates a group results + std::shared_ptr createGroup( + const std::shared_ptr& theFeatureData, const int theIndex = 0); + + std::shared_ptr createParameter( + const std::shared_ptr& theFeatureData, const int theIndex = 0); + + //! Returns a feature by result (owner of result) + std::shared_ptr + feature(const std::shared_ptr& theResult); + + //! Sets the owner of this manager + void setOwner(DocumentPtr theDoc) {myDoc = theDoc;} + + //! Returns the owner of this manager + DocumentPtr owner() {return myDoc;} + + //! Deletes all managed features wit hemmitting of corresponded signal + ~Model_Objects(); + + protected: + + //! Returns (creates if needed) the features label + TDF_Label featuresLabel() const; + + //! Initializes feature with a unique name in this group (unique name is generated as + //! feature type + "_" + index + void setUniqueName(FeaturePtr theFeature); + + //! Synchronizes myFeatures list with the updated document + //! \param theMarkUpdated causes the "update" event for all features + //! \param theUpdateReferences causes the update of back-references + //! \param theFlush makes flush all events in the end of all modifications of this method + void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences, + const bool theFlush); + //! Synchronizes the BackReferences list in Data of Features and Results + void synchronizeBackRefs(); + + //! Creates manager on the OCAF document main label + Model_Objects(TDF_Label theMainLab); + + //! Initializes the data fields of the feature + void initData(ObjectPtr theObj, TDF_Label theLab, const int theTag); + + //! Allows to store the result in the data tree of the document (attaches 'data' of result to tree) + void storeResult(std::shared_ptr theFeatureData, + std::shared_ptr theResult, + const int theResultIndex = 0); + + //! returns the label of result by index; creates this label if it was not created before + TDF_Label resultLabel(const std::shared_ptr& theFeatureData, const int theResultIndex); + + //! Updates the results list of the feature basing on the current data tree + void updateResults(FeaturePtr theFeature); + + /// Internally makes document know that feature was removed or added in history after creation + void updateHistory(const std::shared_ptr theObject); + + /// Internally makes document know that feature was removed or added in history after creation + void updateHistory(const std::string theGroup); + + /// Clears the history arrays related to this object + void clearHistory(ObjectPtr theObj); + + /// Creates the history: up to date with the current state + void createHistory(const std::string& theGroupID); + + /// Returns to the next (from the history point of view) feature, any: invisible or disabled + /// \param theReverse if it is true, iterates in reverced order (next becomes previous) + FeaturePtr nextFeature(FeaturePtr theCurrent, const bool theReverse = false); + /// Returns to the first (from the history point of view) feature, any: invisible or disabled + FeaturePtr firstFeature(); + /// Returns to the last (from the history point of view) feature, any: invisible or disabled + FeaturePtr lastFeature(); + + private: + TDF_Label myMain; ///< main label of the data storage + + DocumentPtr myDoc; ///< doc,ument, owner of this objects manager: needed for events creation + + /// All managed features (not only in history of OB) + /// For optimization mapped by labels + NCollection_DataMap myFeatures; + + /// Map from group id to the array that contains all objects located in history. + /// Each array is updated by demand from scratch, by browing all the features in the history. + std::map > myHistory; + + friend class Model_Document; + friend class Model_Session; + friend class Model_Update; + friend class Model_AttributeReference; + friend class Model_AttributeRefAttr; + friend class Model_AttributeRefList; +}; + +#endif diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index 7708c92cf..9b639f9a7 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -10,9 +10,10 @@ #include #include #include +#include #include +#include #include -#include #include #include #include @@ -50,13 +51,51 @@ void Model_ResultBody::initAttributes() } void Model_ResultBody::colorConfigInfo(std::string& theSection, std::string& theName, - std::string& theDefault) + std::string& theDefault) { theSection = "Visualization"; theName = "result_body_color"; theDefault = DEFAULT_COLOR(); } +bool Model_ResultBody::setDisabled(std::shared_ptr theThis, const bool theFlag) +{ + bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag); + if (aChanged) { // state is changed, so modifications are needed + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (!aData) // unknown case + return aChanged; + TDF_Label& aShapeLab = aData->shapeLab(); + + std::list > aShapePairs; // to store old and new shapes + Handle(TNaming_NamedShape) aName; + int anEvolution = -1; + if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) { + anEvolution = (int)(aName->Evolution()); + for(TNaming_Iterator anIter(aName); anIter.More(); anIter.Next()) { + aShapePairs.push_back(std::pair + (anIter.OldShape(), anIter.NewShape())); + } + } + // remove old + aShapeLab.ForgetAttribute(TNaming_NamedShape::GetID()); + // create new + TNaming_Builder aBuilder(aShapeLab); + TNaming_Evolution anEvol = (TNaming_Evolution)(anEvolution); + std::list >::iterator aPairsIter = aShapePairs.begin(); + for(; aPairsIter != aShapePairs.end(); aPairsIter++) { + if (theFlag) { // disabled => make selection + aBuilder.Select(aPairsIter->first, aPairsIter->second); + } else if (anEvol == TNaming_GENERATED) { + aBuilder.Generated(aPairsIter->first, aPairsIter->second); + } else if (anEvol == TNaming_MODIFY) { + aBuilder.Modify(aPairsIter->first, aPairsIter->second); + } + } + } + return aChanged; +} + void Model_ResultBody::store(const std::shared_ptr& theShape) { std::shared_ptr aData = std::dynamic_pointer_cast(data()); @@ -73,17 +112,17 @@ void Model_ResultBody::store(const std::shared_ptr& theShape) return; // null shape inside aBuilder.Generated(aShape); - // register name - if(!aBuilder.NamedShape()->IsEmpty()) { - Handle(TDataStd_Name) anAttr; - if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) { - std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString()); - if(!aName.empty()) { + // register name + if(!aBuilder.NamedShape()->IsEmpty()) { + Handle(TDataStd_Name) anAttr; + if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) { + std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString()); + if(!aName.empty()) { std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName); - } - } - } + } + } + } } } @@ -106,17 +145,17 @@ void Model_ResultBody::storeGenerated(const std::shared_ptr& theF if (aShapeNew.IsNull()) return; // null shape inside aBuilder.Generated(aShapeBasis, aShapeNew); - // register name - if(!aBuilder.NamedShape()->IsEmpty()) { - Handle(TDataStd_Name) anAttr; - if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) { - std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString()); - if(!aName.empty()) { + // register name + if(!aBuilder.NamedShape()->IsEmpty()) { + Handle(TDataStd_Name) anAttr; + if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) { + std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString()); + if(!aName.empty()) { std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName); - } - } - } + } + } + } } } @@ -138,7 +177,7 @@ void Model_ResultBody::storeModified(const std::shared_ptr& theOl TopoDS_Shape aShapeNew = theNewShape->impl(); if (aShapeNew.IsNull()) return; // null shape inside - aBuilder.Modify(aShapeOld, aShapeNew); + aBuilder.Modify(aShapeOld, aShapeNew); } } @@ -269,7 +308,7 @@ void Model_ResultBody::loadAndOrientModifiedShapes ( ListOfShape aList; std::shared_ptr aRShape(new GeomAPI_Shape()); aRShape->setImpl((new TopoDS_Shape(aRoot))); - theMS->modified(aRShape, aList); + theMS->modified(aRShape, aList); std::list >::const_iterator anIt = aList.begin(), aLast = aList.end(); for (; anIt != aLast; anIt++) { TopoDS_Shape aNewShape = (*anIt)->impl(); @@ -279,9 +318,9 @@ void Model_ResultBody::loadAndOrientModifiedShapes ( } if (!aRoot.IsSame (aNewShape)) { builder(theTag)->Modify(aRoot,aNewShape); - if(!isBuilt) - buildName(theTag, theName); - } + if(!isBuilt) + buildName(theTag, theName); + } } } } @@ -314,17 +353,17 @@ void Model_ResultBody::loadAndOrientGeneratedShapes ( } if (!aRoot.IsSame (aNewShape)) { builder(theTag)->Generated(aRoot,aNewShape); - if(!isBuilt) - buildName(theTag, theName); - } + if(!isBuilt) + buildName(theTag, theName); + } } } } //======================================================================= int getDangleShapes(const TopoDS_Shape& theShapeIn, - const TopAbs_ShapeEnum theGeneratedFrom, - TopTools_DataMapOfShapeShape& theDangles) + const TopAbs_ShapeEnum theGeneratedFrom, + TopTools_DataMapOfShapeShape& theDangles) { theDangles.Clear(); TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors; @@ -343,20 +382,20 @@ int getDangleShapes(const TopoDS_Shape& theShapeIn, //======================================================================= void loadGeneratedDangleShapes( - const TopoDS_Shape& theShapeIn, - const TopAbs_ShapeEnum theGeneratedFrom, - TNaming_Builder * theBuilder) + const TopoDS_Shape& theShapeIn, + const TopAbs_ShapeEnum theGeneratedFrom, + TNaming_Builder * theBuilder) { TopTools_DataMapOfShapeShape dangles; if (!getDangleShapes(theShapeIn, theGeneratedFrom, dangles)) return; TopTools_DataMapIteratorOfDataMapOfShapeShape itr(dangles); for (; itr.More(); itr.Next()) - theBuilder->Generated(itr.Key(), itr.Value()); + theBuilder->Generated(itr.Key(), itr.Value()); } //======================================================================= void Model_ResultBody::loadNextLevels(std::shared_ptr theShape, - const std::string& theName, int& theTag) + const std::string& theName, int& theTag) { if(theShape->isNull()) return; TopoDS_Shape aShape = theShape->impl(); @@ -364,12 +403,12 @@ void Model_ResultBody::loadNextLevels(std::shared_ptr theShape, if (aShape.ShapeType() == TopAbs_SOLID) { TopExp_Explorer expl(aShape, TopAbs_FACE); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } + builder(theTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; + } } else if (aShape.ShapeType() == TopAbs_SHELL || aShape.ShapeType() == TopAbs_FACE) { // load faces and all the free edges @@ -378,84 +417,84 @@ void Model_ResultBody::loadNextLevels(std::shared_ptr theShape, if (Faces.Extent() > 1 || (aShape.ShapeType() == TopAbs_SHELL && Faces.Extent() == 1)) { TopExp_Explorer expl(aShape, TopAbs_FACE); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } + builder(theTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; + } + } TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces; TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, anEdgeAndNeighbourFaces); for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++) - { + { const TopTools_ListOfShape& aLL = anEdgeAndNeighbourFaces.FindFromIndex(i); if (aLL.Extent() < 2) { - if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i)))) + if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i)))) continue; - builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; } else { - TopTools_ListIteratorOfListOfShape anIter(aLL); - const TopoDS_Face& aFace = TopoDS::Face(anIter.Value()); - anIter.Next(); - if(aFace.IsEqual(anIter.Value())) { - builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } - } + TopTools_ListIteratorOfListOfShape anIter(aLL); + const TopoDS_Face& aFace = TopoDS::Face(anIter.Value()); + anIter.Next(); + if(aFace.IsEqual(anIter.Value())) { + builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; + } + } + } } else if (aShape.ShapeType() == TopAbs_WIRE) { TopTools_IndexedMapOfShape Edges; BRepTools::Map3DEdges(aShape, Edges); if (Edges.Extent() == 1) { - builder(++theTag)->Generated(Edges.FindKey(1)); + builder(++theTag)->Generated(Edges.FindKey(1)); TopExp_Explorer expl(aShape, TopAbs_VERTEX); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } else { + builder(theTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; + } + } else { TopExp_Explorer expl(aShape, TopAbs_EDGE); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } + builder(theTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; + } // and load generated vertices. TopTools_DataMapOfShapeShape generated; if (getDangleShapes(aShape, TopAbs_EDGE, generated)) - { - TNaming_Builder* pBuilder = builder(theTag++); - loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder); - } - } + { + TNaming_Builder* pBuilder = builder(theTag++); + loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder); + } + } } else if (aShape.ShapeType() == TopAbs_EDGE) { TopExp_Explorer expl(aShape, TopAbs_VERTEX); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } + builder(theTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; + } } } //======================================================================= int findAmbiguities(const TopoDS_Shape& theShapeIn, - TopTools_ListOfShape& theList) + TopTools_ListOfShape& theList) { int aNumEdges(0); theList.Clear(); @@ -468,36 +507,36 @@ int findAmbiguities(const TopoDS_Shape& theShapeIn, for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) { const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i); const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i); - aMap1.Clear(); + aMap1.Clear(); TopTools_ListIteratorOfListOfShape it(ancestors1); - for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1 - for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) { - if (i == j) continue; + for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1 + for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) { + if (i == j) continue; const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j); const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j); - if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) { - int aNum (ancestors2.Extent()); - TopTools_ListIteratorOfListOfShape it(ancestors2); - for(;it.More();it.Next()) - if(aMap1.Contains(it.Value())) aNum--; - if(aNum == 0) { - if(aMap2.Add(aKeyEdge1)) - aKeyList.Append(aKeyEdge1); - if(aMap2.Add(aKeyEdge2)) - aKeyList.Append(aKeyEdge2); - } - } - } // at the end ==> List of edges to be named in addition + if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) { + int aNum (ancestors2.Extent()); + TopTools_ListIteratorOfListOfShape it(ancestors2); + for(;it.More();it.Next()) + if(aMap1.Contains(it.Value())) aNum--; + if(aNum == 0) { + if(aMap2.Add(aKeyEdge1)) + aKeyList.Append(aKeyEdge1); + if(aMap2.Add(aKeyEdge2)) + aKeyList.Append(aKeyEdge2); + } + } + } // at the end ==> List of edges to be named in addition } aNumEdges = aKeyList.Extent(); if(aNumEdges) - theList.Assign(aKeyList); + theList.Assign(aKeyList); return aNumEdges; } //======================================================================= void Model_ResultBody::loadFirstLevel( - std::shared_ptr theShape, const std::string& theName, int& theTag) + std::shared_ptr theShape, const std::string& theName, int& theTag) { if(theShape->isNull()) return; TopoDS_Shape aShape = theShape->impl(); @@ -505,43 +544,43 @@ void Model_ResultBody::loadFirstLevel( if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) { TopoDS_Iterator itr(aShape); for (; itr.More(); itr.Next(),theTag++) { - builder(theTag)->Generated(itr.Value()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - if(!theName.empty()) buildName(theTag, aName); + builder(theTag)->Generated(itr.Value()); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + if(!theName.empty()) buildName(theTag, aName); if (itr.Value().ShapeType() == TopAbs_COMPOUND || - itr.Value().ShapeType() == TopAbs_COMPSOLID) - { - std::shared_ptr itrShape(new GeomAPI_Shape()); + itr.Value().ShapeType() == TopAbs_COMPSOLID) + { + std::shared_ptr itrShape(new GeomAPI_Shape()); itrShape->setImpl(new TopoDS_Shape(itr.Value())); - loadFirstLevel(itrShape, theName, theTag); + loadFirstLevel(itrShape, theName, theTag); } else { - std::shared_ptr itrShape(new GeomAPI_Shape()); + std::shared_ptr itrShape(new GeomAPI_Shape()); itrShape->setImpl(new TopoDS_Shape(itr.Value())); - loadNextLevels(itrShape, theName, theTag); - } + loadNextLevels(itrShape, theName, theTag); + } } } else { std::shared_ptr itrShape(new GeomAPI_Shape()); itrShape->setImpl(new TopoDS_Shape(aShape)); - loadNextLevels(itrShape, theName, theTag); + loadNextLevels(itrShape, theName, theTag); } TopTools_ListOfShape aList; if(findAmbiguities(aShape, aList)) { - TopTools_ListIteratorOfListOfShape it(aList); + TopTools_ListIteratorOfListOfShape it(aList); for (; it.More(); it.Next(),theTag++) { - builder(theTag)->Generated(it.Value()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - } + builder(theTag)->Generated(it.Value()); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + } } } //======================================================================= void Model_ResultBody::loadDisconnectedEdges( - std::shared_ptr theShape, const std::string& theName, int& theTag) + std::shared_ptr theShape, const std::string& theName, int& theTag) { if(theShape->isNull()) return; TopoDS_Shape aShape = theShape->impl(); @@ -557,33 +596,33 @@ void Model_ResultBody::loadDisconnectedEdges( Standard_Boolean faceIsNew = Standard_True; TopTools_ListIteratorOfListOfShape itrF(edgeNaborFaces.Find(anEdge)); for (; itrF.More(); itrF.Next()) { - if (itrF.Value().IsSame(aFace)) { - faceIsNew = Standard_False; - break; - } - } + if (itrF.Value().IsSame(aFace)) { + faceIsNew = Standard_False; + break; + } + } if (faceIsNew) - edgeNaborFaces.ChangeFind(anEdge).Append(aFace); - } + edgeNaborFaces.ChangeFind(anEdge).Append(aFace); + } } -/* TopTools_IndexedDataMapOfShapeListOfShape aDM; + /* TopTools_IndexedDataMapOfShapeListOfShape aDM; TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, aDM); for(int i=1; i <= aDM.Extent(); i++) { - if(aDM.FindFromIndex(i).Extent() > 1) continue; - if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i)))) - continue; - builder(theTag)->Generated(aDM.FindKey(i)); - TCollection_AsciiString aStr(theTag); - std::string aName = theName + aStr.ToCString(); - buildName(theTag, aName); -#ifdef DEB_IMPORT - aName += + ".brep"; - BRepTools::Write(aDM.FindKey(i), aName.c_str()); -#endif - theTag++; + if(aDM.FindFromIndex(i).Extent() > 1) continue; + if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i)))) + continue; + builder(theTag)->Generated(aDM.FindKey(i)); + TCollection_AsciiString aStr(theTag); + std::string aName = theName + aStr.ToCString(); + buildName(theTag, aName); + #ifdef DEB_IMPORT + aName += + ".brep"; + BRepTools::Write(aDM.FindKey(i), aName.c_str()); + #endif + theTag++; } -*/ + */ TopTools_MapOfShape anEdgesToDelete; TopExp_Explorer anEx(aShape,TopAbs_EDGE); std::string aName; @@ -595,39 +634,39 @@ void Model_ResultBody::loadDisconnectedEdges( if (aList1.Extent()<2) continue; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(edgeNaborFaces); for (; itr.More(); itr.Next()) { - TopoDS_Shape anEdge2 = itr.Key(); - if(anEdgesToDelete.Contains(anEdge2)) continue; - if (anEdge1.IsSame(anEdge2)) continue; - const TopTools_ListOfShape& aList2 = itr.Value(); - // compare lists of the neighbour faces of edge1 and edge2 - if (aList1.Extent() == aList2.Extent()) { - Standard_Integer aMatches = 0; - for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next()) - for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next()) - if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++; - if (aMatches == aList1.Extent()) { - aC0=Standard_True; - builder(theTag)->Generated(anEdge2); - anEdgesToDelete.Add(anEdge2); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } - } + TopoDS_Shape anEdge2 = itr.Key(); + if(anEdgesToDelete.Contains(anEdge2)) continue; + if (anEdge1.IsSame(anEdge2)) continue; + const TopTools_ListOfShape& aList2 = itr.Value(); + // compare lists of the neighbour faces of edge1 and edge2 + if (aList1.Extent() == aList2.Extent()) { + Standard_Integer aMatches = 0; + for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next()) + for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next()) + if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++; + if (aMatches == aList1.Extent()) { + aC0=Standard_True; + builder(theTag)->Generated(anEdge2); + anEdgesToDelete.Add(anEdge2); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; + } + } + } TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete); for(;itDelete.More();itDelete.Next()) - edgeNaborFaces.UnBind(itDelete.Key()); + edgeNaborFaces.UnBind(itDelete.Key()); edgeNaborFaces.UnBind(anEdge1); - } + } if (aC0) { - builder(theTag)->Generated(anEdge1); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } + builder(theTag)->Generated(anEdge1); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; + } } } @@ -662,11 +701,11 @@ void Model_ResultBody::loadDisconnectedVertexes(std::shared_ptr t for (; itr.More(); itr.Next()) { const TopTools_ListOfShape& naborEdges = itr.Value(); if (naborEdges.Extent() < 2) { - builder(theTag)->Generated(itr.Key()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } + builder(theTag)->Generated(itr.Key()); + TCollection_AsciiString aStr(theTag); + aName = theName + aStr.ToCString(); + buildName(theTag, aName); + theTag++; + } } } diff --git a/src/Model/Model_ResultBody.h b/src/Model/Model_ResultBody.h index a5ffd8302..befed5622 100644 --- a/src/Model/Model_ResultBody.h +++ b/src/Model/Model_ResultBody.h @@ -39,10 +39,15 @@ public: /// Request for initialization of data model of the result: adding all attributes virtual void initAttributes(); - // Retuns the parameters of color definition in the resources config manager + /// Returns the parameters of color definition in the resources config manager MODEL_EXPORT virtual void colorConfigInfo(std::string& theSection, std::string& theName, std::string& theDefault); + /// Disables the result body: keeps the resulting shape as selection, but erases the underlaying + /// naming data structure if theFlag if false. Or restores everything on theFlag is true. + MODEL_EXPORT virtual bool setDisabled(std::shared_ptr theThis, + const bool theFlag); + /// Stores the shape (called by the execution method). MODEL_EXPORT virtual void store(const std::shared_ptr& theShape); @@ -130,7 +135,7 @@ private: /// builds name for the shape kept at the specified tag void buildName(const int theTag, const std::string& theName); - friend class Model_Document; + friend class Model_Objects; }; #endif diff --git a/src/Model/Model_ResultConstruction.h b/src/Model/Model_ResultConstruction.h index 84f048f6d..9c7ccd57d 100644 --- a/src/Model/Model_ResultConstruction.h +++ b/src/Model/Model_ResultConstruction.h @@ -63,7 +63,7 @@ class Model_ResultConstruction : public ModelAPI_ResultConstruction /// Makes a body on the given feature Model_ResultConstruction(); - friend class Model_Document; + friend class Model_Objects; }; #endif diff --git a/src/Model/Model_ResultGroup.h b/src/Model/Model_ResultGroup.h index 7bfa79694..63e8368f4 100644 --- a/src/Model/Model_ResultGroup.h +++ b/src/Model/Model_ResultGroup.h @@ -43,7 +43,7 @@ protected: /// Makes a body on the given feature data Model_ResultGroup(std::shared_ptr theOwnerData); - friend class Model_Document; + friend class Model_Objects; }; #endif diff --git a/src/Model/Model_ResultParameter.h b/src/Model/Model_ResultParameter.h index 641155b1e..7d3ca5985 100644 --- a/src/Model/Model_ResultParameter.h +++ b/src/Model/Model_ResultParameter.h @@ -26,7 +26,7 @@ class Model_ResultParameter : public ModelAPI_ResultParameter protected: Model_ResultParameter(); - friend class Model_Document; + friend class Model_Objects; }; #endif diff --git a/src/Model/Model_ResultPart.h b/src/Model/Model_ResultPart.h index cda7bf6cd..7ebafd3ea 100644 --- a/src/Model/Model_ResultPart.h +++ b/src/Model/Model_ResultPart.h @@ -38,7 +38,7 @@ protected: /// Returns true if document is activated (loaded into the memory) virtual bool isActivated(); - friend class Model_Document; + friend class Model_Objects; }; #endif diff --git a/src/Model/Model_Session.cpp b/src/Model/Model_Session.cpp index 69c2f1b16..921e964cb 100644 --- a/src/Model/Model_Session.cpp +++ b/src/Model/Model_Session.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -216,7 +217,7 @@ void Model_Session::setActiveDocument( if (aDoc.get()) { bool aWasChecked = myCheckTransactions; setCheckTransactions(false); - aDoc->synchronizeFeatures(false, true, true); + aDoc->objects()->synchronizeFeatures(false, true, true); if (aWasChecked) setCheckTransactions(true); } @@ -266,7 +267,7 @@ std::shared_ptr Model_Session::copy( aRT->SetRelocation(aSourceRoot, aTargetRoot); TDF_CopyTool::Copy(aDS, aRT); - aNew->synchronizeFeatures(false, true, true); + aNew->objects()->synchronizeFeatures(false, true, true); return aNew; } diff --git a/src/Model/Model_Session.h b/src/Model/Model_Session.h index 47e40262e..ebfef43d0 100644 --- a/src/Model/Model_Session.h +++ b/src/Model/Model_Session.h @@ -122,6 +122,7 @@ class Model_Session : public ModelAPI_Session, public Events_Listener FeaturePtr createFeature(std::string theFeatureID, Model_Document* theDocOwner); friend class Model_Document; + friend class Model_Objects; }; #endif diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 72daf2082..faa0ec14b 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -166,15 +167,16 @@ void Model_Update::updateInDoc(std::shared_ptr theDoc) { std::set alreadyProcessed; // features that are processed before others // all features one by one - for (int aFIndex = 0; aFIndex < theDoc->size(ModelAPI_Feature::group(), true); aFIndex++) { - FeaturePtr aFeature = std::dynamic_pointer_cast( - theDoc->object(ModelAPI_Feature::group(), aFIndex, true)); - if (aFeature && alreadyProcessed.find(aFeature) == alreadyProcessed.end()) { + Model_Objects* anObjs = std::dynamic_pointer_cast(theDoc)->objects(); + if (!anObjs) return; + FeaturePtr aFeatureIter = anObjs->firstFeature(); + for (; aFeatureIter.get(); aFeatureIter = anObjs->nextFeature(aFeatureIter)) { + if (aFeatureIter && alreadyProcessed.find(aFeatureIter) == alreadyProcessed.end()) { // update selection and parameters attributes first, before sub-features analysis (sketch plane) - updateArguments(aFeature); + updateArguments(aFeatureIter); // composite feature must be executed after sub-features execution CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(aFeature); + std::dynamic_pointer_cast(aFeatureIter); if (aComposite) { // number of subs can be changed in execution: like fillet for(int a = 0; a < aComposite->numberOfSubs(); a++) { @@ -184,14 +186,14 @@ void Model_Update::updateInDoc(std::shared_ptr theDoc) } } - updateFeature(aFeature); + updateFeature(aFeatureIter); // update the document results recursively - const std::list >& aResults = aFeature->results(); + const std::list >& aResults = aFeatureIter->results(); std::list >::const_iterator aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { ResultPartPtr aPart = std::dynamic_pointer_cast(*aRIter); if (aPart.get()) { - if (aPart->isActivated()) { + if (!aPart->isDisabled() && aPart->isActivated()) { updateInDoc(aPart->partDoc()); } } diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index be7fa566c..4248ea23a 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -67,10 +67,8 @@ public: //! Returns the object in the group by the index (started from zero) //! \param theGroupID group that contains an object //! \param theIndex zero-based index of feature in the group - //! \param theHidden if it is true, it counts also the features that are not in tree virtual std::shared_ptr object(const std::string& theGroupID, - const int theIndex, - const bool theHidden = false) = 0; + const int theIndex) = 0; //! Returns the first found object in the group by the object name //! \param theGroupID group that contains an object @@ -85,8 +83,7 @@ public: virtual const int index(std::shared_ptr theObject) = 0; //! Returns the number of objects in the group of objects - //! If theHidden is true, it counts also the features that are not in tree - virtual int size(const std::string& theGroupID, const bool theHidden = false) = 0; + virtual int size(const std::string& theGroupID) = 0; //! Returns the feature that is currently edited in this document, normally //! this is the latest created feature @@ -129,9 +126,12 @@ protected: MODELAPI_EXPORT ModelAPI_Document(); /// Internally makes document know that feature was removed or added in history after creation - MODELAPI_EXPORT virtual void addToHistory(const std::shared_ptr theObject) = 0; + MODELAPI_EXPORT virtual void updateHistory(const std::shared_ptr theObject) = 0; + /// Internally makes document know that feature was removed or added in history after creation + MODELAPI_EXPORT virtual void updateHistory(const std::string theGroup) = 0; friend class ModelAPI_Object; // to add or remove from the history + friend class ModelAPI_Result; // to add or remove from the history }; //! Pointer on document object diff --git a/src/ModelAPI/ModelAPI_Feature.cpp b/src/ModelAPI/ModelAPI_Feature.cpp index 1a756e2d8..e7c16599a 100644 --- a/src/ModelAPI/ModelAPI_Feature.cpp +++ b/src/ModelAPI/ModelAPI_Feature.cpp @@ -29,22 +29,24 @@ std::shared_ptr ModelAPI_Feature::lastResult() void ModelAPI_Feature::setResult(const std::shared_ptr& theResult) { - if (firstResult() == theResult) { // just updated - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); - ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent); - return; - } - // created - while (!myResults.empty()) { // remove one by one with messages - std::shared_ptr aRes = *(myResults.begin()); - myResults.erase(myResults.begin()); - ModelAPI_EventCreator::get()->sendDeleted(aRes->document(), aRes->groupName()); + static Events_Loop* aLoop = Events_Loop::loop(); + static Events_ID EVENT_UPD = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); + + if (firstResult() == theResult) { + // nothing to change + } else if (!myResults.empty()) { // all except first become disabled + std::list >::iterator aResIter = myResults.begin(); + *aResIter = theResult; + aECreator->sendUpdated(theResult, EVENT_UPD); + for(aResIter++; aResIter != myResults.end(); aResIter++) { + (*aResIter)->setDisabled((*aResIter), true); + } + } else { + myResults.push_back(theResult); } - myResults.push_back(theResult); - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent); - // Create event for first Feature - Events_Loop::loop()->flush(anEvent); + // in any case result decomes enabled + theResult->setDisabled(theResult, false); } void ModelAPI_Feature::setResult(const std::shared_ptr& theResult, @@ -56,80 +58,31 @@ void ModelAPI_Feature::setResult(const std::shared_ptr& theResu } if (aResIter == myResults.end()) { // append myResults.push_back(theResult); - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent); - // Create event for first Feature, send it to make "created" earlier than "updated" - // VSV: Commenting out of this statement causes problems with circle operation for example - Events_Loop::loop()->flush(anEvent); } else { // update *aResIter = theResult; - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); - ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent); } + theResult->setDisabled(theResult, false); } void ModelAPI_Feature::removeResult(const std::shared_ptr& theResult) { - std::list >::iterator aResIter = myResults.begin(); - for(; aResIter != myResults.end(); aResIter++) { - ResultPtr aRes = *aResIter; - if (aRes == theResult) { - std::string aGroup = aRes->groupName(); - aRes->data()->erase(); - myResults.erase(aResIter); - - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); - static Events_Loop* aLoop = Events_Loop::loop(); - static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); - static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); - ModelAPI_EventCreator::get()->sendDeleted(document(), aGroup); - aECreator->sendUpdated(aRes, EVENT_DISP); - break; - } - } + theResult->setDisabled(theResult, true); } void ModelAPI_Feature::removeResults(const int theSinceIndex) { - if (theSinceIndex == 0) { - eraseResults(); - return; - } - std::list >::iterator aResIter = myResults.begin(); for(int anIndex = 0; anIndex < theSinceIndex && aResIter != myResults.end(); anIndex++) aResIter++; std::list >::iterator aNextIter = aResIter; for(; aNextIter != myResults.end(); aNextIter++) { - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); - static Events_Loop* aLoop = Events_Loop::loop(); - static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); - static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); - ModelAPI_EventCreator::get()->sendDeleted(document(), (*aNextIter)->groupName()); - aECreator->sendUpdated(*aNextIter, EVENT_DISP); + (*aNextIter)->setDisabled(*aNextIter, true); // just disable results } - myResults.erase(aResIter, myResults.end()); } void ModelAPI_Feature::eraseResults() { - if (!myResults.empty()) { - static Events_Loop* aLoop = Events_Loop::loop(); - static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); - static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); - - std::list >::iterator aResIter = myResults.begin(); - for(; aResIter != myResults.end(); aResIter++) { - (*aResIter)->data()->erase(); - ModelAPI_EventCreator::get()->sendDeleted(document(), (*aResIter)->groupName()); - aECreator->sendUpdated(*aResIter, EVENT_DISP); - } - myResults.clear(); - // flush it to avoid left presentations after input of invalid arguments (radius=0) - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); - Events_Loop::loop()->flush(anEvent); - Events_Loop::loop()->flush(EVENT_DISP); - } + removeResults(0); } const std::string& ModelAPI_Feature::documentToAdd() diff --git a/src/ModelAPI/ModelAPI_Object.cpp b/src/ModelAPI/ModelAPI_Object.cpp index 573b2d12f..9d07e42aa 100644 --- a/src/ModelAPI/ModelAPI_Object.cpp +++ b/src/ModelAPI/ModelAPI_Object.cpp @@ -17,7 +17,7 @@ void ModelAPI_Object::setInHistory( { if (myInHistory != theFlag) { myInHistory = theFlag; - myDoc->addToHistory(theObject); + myDoc->updateHistory(theObject); } } diff --git a/src/ModelAPI/ModelAPI_Object.h b/src/ModelAPI/ModelAPI_Object.h index f04d10ad5..b13420f07 100644 --- a/src/ModelAPI/ModelAPI_Object.h +++ b/src/ModelAPI/ModelAPI_Object.h @@ -74,7 +74,7 @@ class ModelAPI_Object /// removes all fields from this feature MODELAPI_EXPORT virtual void erase(); - friend class Model_Document; + friend class Model_Objects; }; diff --git a/src/ModelAPI/ModelAPI_Result.cpp b/src/ModelAPI/ModelAPI_Result.cpp index d43592014..c16732d99 100644 --- a/src/ModelAPI/ModelAPI_Result.cpp +++ b/src/ModelAPI/ModelAPI_Result.cpp @@ -12,9 +12,45 @@ ModelAPI_Result::~ModelAPI_Result() { +} +bool ModelAPI_Result::setDisabled(std::shared_ptr theThis, const bool theFlag) +{ + if (myIsDisabled != theFlag) { + myIsDisabled = theFlag; + // 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 + static Events_Loop* aLoop = Events_Loop::loop(); + static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); + if (myIsDisabled) { // disabled result looks like removed + aECreator->sendDeleted(document(), groupName()); + } else { // un-disabled equals to created + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); + aECreator->sendUpdated(theThis, anEvent, false); // do not group: creation must be immediate + } + static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + aECreator->sendUpdated(theThis, EVENT_DISP, false); + return true; + } + return false; +} + +bool ModelAPI_Result::isDisabled() const +{ + return myIsDisabled; } +void ModelAPI_Result::setIsConcealed(const bool theValue) +{ + if (myIsConcealed != theValue) { + myIsConcealed = theValue; + if (document().get()) // can be on creation of result + document()->updateHistory(groupName()); // to update the history cash data in the document + } +} + + std::shared_ptr ModelAPI_Result::shape() { return std::shared_ptr(); diff --git a/src/ModelAPI/ModelAPI_Result.h b/src/ModelAPI/ModelAPI_Result.h index 635649f5c..dedee45d7 100644 --- a/src/ModelAPI/ModelAPI_Result.h +++ b/src/ModelAPI/ModelAPI_Result.h @@ -21,6 +21,7 @@ class ModelAPI_Feature; class ModelAPI_Result : public ModelAPI_Object { bool myIsConcealed; ///< the result is concealed from the data tree (referenced by other objects) + bool myIsDisabled; ///< the result is disabled: removed for the user, but keeps the general info public: /// Reference to the color of the result. @@ -39,10 +40,19 @@ class ModelAPI_Result : public ModelAPI_Object } /// Returns true if the result is concealed from the data tree (referenced by other objects) - inline void setIsConcealed(const bool theValue) - { - myIsConcealed = theValue; - } + MODELAPI_EXPORT void setIsConcealed(const bool theValue); + + /// Enables/disables the result. The disabled result does not participate in any calculation + /// and visualization: like it was removed. But it keeps the general parameters: colors, + /// visibility, etc. + /// \param theThis pointer to this object, needed to generate all events if it is neccessary + /// \param theFlag makes disabled if it is true + /// \returns true if state is really changed + MODELAPI_EXPORT virtual bool setDisabled(std::shared_ptr theThis, + const bool theFlag); + + /// Returns the result is disabled or not. + MODELAPI_EXPORT virtual bool isDisabled() const; // Retuns the parameters of color definition in the resources config manager virtual void colorConfigInfo(std::string& theSection, std::string& theName,