X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Document.cpp;h=082a6c60fd51f13be8e96a2cacab2d9b536eac75;hb=4c74e5b864eef28128e27b3ece944990ca8f3fbe;hp=4c584ea7782798ee426295b2ebb89574e8482caa;hpb=986dc88bed752ebed1828eb3d54461480e2435f9;p=modules%2Fshaper.git diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp old mode 100755 new mode 100644 index 4c584ea77..082a6c60f --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2019 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -12,10 +12,9 @@ // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include @@ -32,6 +31,7 @@ #include #include #include +#include #include #include @@ -44,20 +44,24 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include +#include #include #include #include #include #include #include +#include +#include +#include #include #include @@ -92,6 +96,9 @@ static const int TAG_NODES_STATE = 4; ///< array, tag of the Object Browser node ///< naming structures constructions selected from other document static const int TAG_EXTERNAL_CONSTRUCTIONS = 5; +/// reference to the shape in external document: sting list attribute identifier +static const Standard_GUID kEXTERNAL_SHAPE_REF("9aa5dd14-6d34-4a8d-8786-05842fd7bbbd"); + Model_Document::Model_Document(const int theID, const std::string theKind) : myID(theID), myKind(theKind), myIsActive(false), myIsSetCurrentFeature(false), myDoc(new TDocStd_Document("BinOcaf")) // binary OCAF format @@ -136,6 +143,84 @@ bool Model_Document::isRoot() const return this == Model_Session::get()->moduleDocument().get(); } +// LCOV_EXCL_START +/// Makes all modification and generation naming shapes that have old shapes corresponding to +/// shapes in a root document be equal to this root document +static void updateShapesFromRoot(const TDF_Label theThisAccess, const TDF_Label theRootAccess) +{ + TopTools_DataMapOfShapeShape aCurrentToRoot; // shapes that must be updated: from this to root + TDF_ChildIDIterator aThisIter(theThisAccess.Root(), kEXTERNAL_SHAPE_REF, true); + for(; aThisIter.More(); aThisIter.Next()) { + aCurrentToRoot.Clear(); + Handle(TNaming_NamedShape) aNS; + if (!aThisIter.Value()->Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) + continue; + if (aNS->Evolution() != TNaming_GENERATED && aNS->Evolution() != TNaming_MODIFY) + continue; + for (TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) { + const TopoDS_Shape& anOld = aNSIter.OldShape(); + if (anOld.IsNull()) + continue; + TNaming_OldShapeIterator aNewIter(anOld, theThisAccess); + for (; aNewIter.More(); aNewIter.Next()) { + TNaming_Evolution anEvolution = aNewIter.NamedShape()->Evolution(); + if (anEvolution != TNaming_SELECTED && anEvolution != TNaming_DELETE) + break; + } + if (aNewIter.More()) + continue; + GeomShapePtr anOldShape(new GeomAPI_Shape), aRootShape(new GeomAPI_Shape); + anOldShape->setImpl(new TopoDS_Shape(anOld)); + anOldShape = GeomAPI_Tools::getTypedShape(anOldShape); + + // search the same shape in the root document + Handle(TDataStd_ExtStringList) anEntries = + Handle(TDataStd_ExtStringList)::DownCast(aThisIter.Value()); + TDataStd_ListOfExtendedString::Iterator anIter(anEntries->List()); + for (; anIter.More(); anIter.Next()) { + TDF_Label aRootLab; + TDF_Tool::Label(theRootAccess.Data(), anIter.Value(), aRootLab); + if (aRootLab.IsNull()) + continue; + Handle(TNaming_NamedShape) aRootNS; + if (!aRootLab.FindAttribute(TNaming_NamedShape::GetID(), aRootNS)) + continue; + TNaming_Iterator aRootShapes(aRootNS); + for (; aRootShapes.More(); aRootShapes.Next()) { + if (aRootShapes.NewShape().IsNull()) + continue; + aRootShape->setImpl(new TopoDS_Shape(aRootShapes.NewShape())); + aRootShape = GeomAPI_Tools::getTypedShape(aRootShape); + if (!anOldShape->isEqual(aRootShape)) // special checking by geometry + continue; + // found a good corresponded shape + if (!anOld.IsEqual(aRootShapes.NewShape())) + aCurrentToRoot.Bind(anOld, aRootShapes.NewShape()); + } + } + } + if (!aCurrentToRoot.IsEmpty()) { // update the whole named shape content + TopTools_ListOfShape anOld, aNew; + TNaming_Evolution anEvol = aNS->Evolution(); + for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) { + anOld.Prepend(aCurrentToRoot.IsBound(aNSIter.OldShape()) ? + aCurrentToRoot.Find(aNSIter.OldShape()) : aNSIter.OldShape()); + aNew.Prepend(aNSIter.NewShape()); + } + TNaming_Builder aBuilder(aNS->Label()); + TopTools_ListOfShape::Iterator anOldIter(anOld), aNewIter(aNew); + for(; anOldIter.More(); anOldIter.Next(), aNewIter.Next()) { + if (anEvol == TNaming_GENERATED) { + aBuilder.Generated(anOldIter.Value(), aNewIter.Value()); + } else if (anEvol == TNaming_MODIFY) { + aBuilder.Modify(anOldIter.Value(), aNewIter.Value()); + } + } + } + } +} +// LCOV_EXCL_STOP + bool Model_Document::load(const char* theDirName, const char* theFileName, DocumentPtr theThis) { Handle(Model_Application) anApp = Model_Application::getApplication(); @@ -154,6 +239,7 @@ bool Model_Document::load(const char* theDirName, const char* theFileName, Docum } bool isError = aStatus != PCDM_RS_OK; if (isError) { + // LCOV_EXCL_START switch (aStatus) { case PCDM_RS_UnknownDocument: Events_InfoMessage("Model_Document", "Can not open document").send(); @@ -208,6 +294,7 @@ bool Model_Document::load(const char* theDirName, const char* theFileName, Docum Events_InfoMessage("Model_Document", "Can not open document: unknown error").send(); break; } + // LCOV_EXCL_STOP } std::shared_ptr aSession = std::dynamic_pointer_cast(Model_Session::get()); @@ -225,7 +312,7 @@ bool Model_Document::load(const char* theDirName, const char* theFileName, Docum // update the current features status setCurrentFeature(currentFeature(false), false); aSession->setCheckTransactions(true); - aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false); + aSession->setActiveDocument(aSession->moduleDocument(), false); // this is done in Part result "activate", so no needed here. Causes not-blue active part. // aSession->setActiveDocument(anApp->getDocument(myID), true); @@ -239,7 +326,10 @@ bool Model_Document::load(const char* theDirName, const char* theFileName, Docum anApp->setLoadByDemand(aPart->data()->name(), aPart->data()->document(ModelAPI_ResultPart::DOC_REF())->docId()); } - + if (!isRoot()) { + updateShapesFromRoot(myDoc->Main(), + std::dynamic_pointer_cast(aSession->moduleDocument())->generalLabel()); + } } else { // open failed, but new document was created to work with it: inform the model aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false); } @@ -274,7 +364,10 @@ bool Model_Document::save( Handle(Model_Application) anApp = Model_Application::getApplication(); if (isRoot()) { #ifdef WIN32 - CreateDirectory((LPTSTR) theDirName, NULL); + size_t aDirLen = strlen(theDirName); + std::wstring aWStr(aDirLen, L'#'); + mbstowcs(&aWStr[0], theDirName, aDirLen); + CreateDirectory(aWStr.c_str(), NULL); #else mkdir(theDirName, 0x1ff); #endif @@ -580,10 +673,10 @@ bool Model_Document::finishOperation() } myObjs->synchronizeBackRefs(); Events_Loop* aLoop = Events_Loop::loop(); - static const Events_ID kCreatedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED); - static const Events_ID kUpdatedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED); - static const Events_ID kRedispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - static const Events_ID kDeletedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED); + static const Events_ID kCreatedEvent = aLoop->eventByName(EVENT_OBJECT_CREATED); + static const Events_ID kUpdatedEvent = aLoop->eventByName(EVENT_OBJECT_UPDATED); + static const Events_ID kRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + static const Events_ID kDeletedEvent = aLoop->eventByName(EVENT_OBJECT_DELETED); aLoop->flush(kCreatedEvent); aLoop->flush(kUpdatedEvent); aLoop->flush(kRedispEvent); @@ -862,7 +955,8 @@ void Model_Document::redo() // update the current features status setCurrentFeature(currentFeature(false), false); } - +// this is used for creation of undo/redo1-list by GUI +// LCOV_EXCL_START std::list Model_Document::undoList() const { std::list aResult; @@ -888,6 +982,7 @@ std::list Model_Document::redoList() const } return aResult; } +// LCOV_EXCL_STOP void Model_Document::operationId(const std::string& theId) { @@ -929,6 +1024,15 @@ FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurre aCurrent = aSub; } } + // #2861: if the parameter is added, add it after parameters existing in the list + if (aCurrent.get() && + (aFeature->getKind() == "Parameter" || aFeature->getKind() == "ParametersMgr")) { + int anIndex = kUNDEFINED_FEATURE_INDEX; + for(FeaturePtr aNextFeat = myObjs->nextFeature(aCurrent, anIndex); + aNextFeat.get() && aNextFeat->getKind() == "Parameter"; + aNextFeat = myObjs->nextFeature(aCurrent, anIndex)) + aCurrent = aNextFeat; + } } aDocToAdd->myObjs->addFeature(aFeature, aCurrent); if (!aFeature->isAction()) { // do not add action to the data model @@ -942,7 +1046,6 @@ FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurre return aFeature; } - void Model_Document::refsToFeature(FeaturePtr theFeature, std::set >& theRefs, const bool isSendError) { @@ -953,7 +1056,7 @@ void Model_Document::removeFeature(FeaturePtr theFeature) { myObjs->removeFeature(theFeature); // fix for #2723: send signal that part is updated - if (!isRoot()) { + if (!isRoot() && isOperation()) { std::shared_ptr aRoot = std::dynamic_pointer_cast(ModelAPI_Session::get()->moduleDocument()); std::list allParts; @@ -981,7 +1084,6 @@ static bool isSub(const CompositeFeaturePtr theMain, const FeaturePtr theSub) { return isSub(theMain, aParent); } - void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) { bool aCurrentUp = theMoved == currentFeature(false); @@ -995,8 +1097,9 @@ void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) FeaturePtr anAfterThisSub = theAfterThis; if (aCompositeAfter.get()) { FeaturePtr aSub = aCompositeAfter; + int anIndex = kUNDEFINED_FEATURE_INDEX; do { - FeaturePtr aNext = myObjs->nextFeature(aSub); + FeaturePtr aNext = myObjs->nextFeature(aSub, anIndex); if (!isSub(aCompositeAfter, aNext)) { anAfterThisSub = aSub; break; @@ -1092,8 +1195,9 @@ std::shared_ptr Model_Document::currentFeature(const bool theV TDF_Label aLab = aRef->Get(); FeaturePtr aResult = myObjs->feature(aLab); if (theVisible) { // get nearest visible (in history) going up + int anIndex = kUNDEFINED_FEATURE_INDEX; while(aResult.get() && !aResult->isInHistory()) { - aResult = myObjs->nextFeature(aResult, true); + aResult = myObjs->nextFeature(aResult, anIndex, true); } } return aResult; @@ -1129,9 +1233,10 @@ void Model_Document::setCurrentFeature( if (theVisible && !theCurrent.get()) { // needed to avoid disabling of PartSet initial constructions + int anIndex = kUNDEFINED_FEATURE_INDEX; FeaturePtr aNext = - theCurrent.get() ? myObjs->nextFeature(theCurrent) : myObjs->firstFeature(); - for (; aNext.get(); aNext = myObjs->nextFeature(theCurrent)) { + theCurrent.get() ? myObjs->nextFeature(theCurrent, anIndex, false) : myObjs->firstFeature(); + for (; aNext.get(); aNext = myObjs->nextFeature(theCurrent, anIndex, false)) { if (aNext->isInHistory()) { break; // next in history is not needed } else { // next not in history is good for making current @@ -1139,6 +1244,18 @@ void Model_Document::setCurrentFeature( } } } + if (theVisible) { // make RemoveResults feature be active even it is performed after the current + int anIndex = kUNDEFINED_FEATURE_INDEX; + FeaturePtr aNext = + theCurrent.get() ? myObjs->nextFeature(theCurrent, anIndex, false) : myObjs->firstFeature(); + for (; aNext.get(); aNext = myObjs->nextFeature(theCurrent, anIndex, false)) { + if (aNext->isInHistory()) { + break; // next in history is not needed + } else if (aNext->getKind() == "RemoveResults"){ + theCurrent = aNext; + } + } + } if (theCurrent.get()) { std::shared_ptr aData = std::static_pointer_cast(theCurrent->data()); if (!aData.get() || !aData->isValid()) { @@ -1165,7 +1282,8 @@ void Model_Document::setCurrentFeature( FeaturePtr anIter = myObjs->lastFeature(); bool aWasChanged = false; bool isCurrentParameter = theCurrent.get() && theCurrent->getKind() == "Parameter"; - for(; anIter.get(); anIter = myObjs->nextFeature(anIter, true)) { + int anIndex = kUNDEFINED_FEATURE_INDEX; + for(; anIter.get(); anIter = myObjs->nextFeature(anIter, anIndex, true)) { // check this before passed become enabled: the current feature is enabled! if (anIter == theCurrent) aPassed = true; @@ -1227,7 +1345,8 @@ void Model_Document::setCurrentFeatureUp() // problems if it is true: here and in "setCurrentFeature" FeaturePtr aCurrent = currentFeature(false); if (aCurrent.get()) { // if not, do nothing because null is the upper - FeaturePtr aPrev = myObjs->nextFeature(aCurrent, true); + int anIndex = kUNDEFINED_FEATURE_INDEX; + FeaturePtr aPrev = myObjs->nextFeature(aCurrent, anIndex, true); // make the higher level composite as current (sketch becomes disabled if line is enabled) if (aPrev.get()) { FeaturePtr aComp = ModelAPI_Tools::compositeOwner(aPrev); @@ -1342,16 +1461,6 @@ std::shared_ptr Model_Document::feature( return myObjs->feature(theResult); } -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); -} - FeaturePtr Model_Document::featureByLab(const TDF_Label& theLab) { TDF_Label aCurrentLab = theLab; while(aCurrentLab.Depth() > 3) @@ -1372,7 +1481,6 @@ ResultPtr Model_Document::resultByLab(const TDF_Label& theLab) return ResultPtr(); // not found } - void Model_Document::addNamingName(const TDF_Label theLabel, std::string theName) { std::map >::iterator aFind = myNamingNames.find(theName); @@ -1428,7 +1536,7 @@ void Model_Document::changeNamingName(const std::string theOldName, Handle(TDataStd_Name) aSubName = Handle(TDataStd_Name)::DownCast(aChild.Value()); std::string aName = TCollection_AsciiString(aSubName->Get()).ToCString(); if (aName.find(theOldName) == 0) { // started from parent name - std::string aNewSubName = theNewName + aName.substr(theNewName.size()); + std::string aNewSubName = theNewName + aName.substr(theOldName.size()); changeNamingName(aName, aNewSubName, aSubName->Label()); aSubName->Set(aNewSubName.c_str()); } @@ -1525,14 +1633,21 @@ bool Model_Document::isLaterByDep(FeaturePtr theThis, FeaturePtr theOther) { if (aRefFeat.get()) { if (aRefFeat == theThis) return false; // other references to this, so other later than this - if (std::dynamic_pointer_cast(aRefFeat)) { - if (!isLaterByDep(theThis, aRefFeat)) // nested composites: recursion - return false; - } + //if (std::dynamic_pointer_cast(aRefFeat)) { + // if (!isLaterByDep(theThis, aRefFeat)) // nested composites: recursion + // return false; + //} } } } } + FeaturePtr aThisOwner = ModelAPI_Tools::compositeOwner(theThis); + if (aThisOwner.get()) { + if (aThisOwner == theOther) + return true; // composite owner is later that its sub + if (!isLaterByDep(aThisOwner, theOther)) + return false; + } return myObjs->isLater(theThis, theOther); } @@ -1659,11 +1774,6 @@ void Model_Document::incrementTransactionID() int aNewVal = transactionID() + 1; TDataStd_Integer::Set(generalLabel().FindChild(TAG_CURRENT_TRANSACTION), aNewVal); } -void Model_Document::decrementTransactionID() -{ - int aNewVal = transactionID() - 1; - TDataStd_Integer::Set(generalLabel().FindChild(TAG_CURRENT_TRANSACTION), aNewVal); -} TDF_Label Model_Document::extConstructionsLabel() const { @@ -1685,11 +1795,6 @@ std::shared_ptr Model_Document::internalFeature(const int theI return myObjs->internalFeature(theIndex); } -std::shared_ptr Model_Document::featureById(const int theId) -{ - return myObjs->featureById(theId); -} - void Model_Document::synchronizeTransactions() { Model_Document* aRoot = @@ -1828,7 +1933,7 @@ std::shared_ptr Model_Document::producedByFeature( TopoDS_Shape anOldShape; // old shape in the pair old shape->theShape in the named shape TopoDS_Shape aShapeContainer; // old shape of the shape that contains aShape as sub-element Handle(TNaming_NamedShape) aCandidatInThis, aCandidatContainer; - TDF_Label aBodyLab = aBodyData->label(); + TDF_Label aBodyLab = aBodyData->shapeLab(); // use child and this label (the lowest priority) TDF_ChildIDIterator aNSIter(aBodyLab, TNaming_NamedShape::GetID(), Standard_True); bool aUseThis = !aNSIter.More(); @@ -1909,6 +2014,8 @@ bool Model_Document::isLater(FeaturePtr theLater, FeaturePtr theCurrent) const return myObjs->isLater(theLater, theCurrent); } +// Object Browser nodes states +// LCOV_EXCL_START void Model_Document::storeNodesState(const std::list& theStates) { TDF_Label aLab = generalLabel().FindChild(TAG_NODES_STATE); @@ -1934,6 +2041,7 @@ void Model_Document::restoreNodesState(std::list& theStates) const } } } +// LCOV_EXCL_STOP void Model_Document::eraseAllFeatures() { @@ -1941,6 +2049,16 @@ void Model_Document::eraseAllFeatures() myObjs->eraseAllFeatures(); } +std::shared_ptr Model_Document::nextFeature( + std::shared_ptr theCurrent, const bool theReverse) const +{ + if (theCurrent.get() && myObjs) { + int anIndex = kUNDEFINED_FEATURE_INDEX; + return myObjs->nextFeature(theCurrent, anIndex, theReverse); + } + return FeaturePtr(); // nothing by default +} + void Model_Document::setExecuteFeatures(const bool theFlag) { myExecuteFeatures = theFlag;