X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Document.cpp;h=94903c205b044a660676fc5b2cc9ae43219adca8;hb=745c72679f6346375d5e886b25cc3865f3c4daae;hp=2fbfac44901166c19f5285017626a5170a3a4546;hpb=f39d4f0ba6a24326c08dc70fbbd44b9322104973;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 2fbfac449..94903c205 --- 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-2021 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 @@ -24,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +34,8 @@ #include #include +#include + #include #include #include @@ -60,17 +62,24 @@ #include #include #include -#include +#include #include #include #include #include +#include #include #include +#include + +#ifdef TINSPECTOR #include #include +#endif + +#include #include #ifndef WIN32 @@ -101,8 +110,11 @@ static const int TAG_EXTERNAL_CONSTRUCTIONS = 5; 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 + : myID(theID), + myKind(theKind), + myDoc(new TDocStd_Document("BinOcaf")), // binary OCAF format + myIsActive(false), + myIsSetCurrentFeature(false) { #ifdef TINSPECTOR CDF_Session::CurrentSession()->Directory()->Add(myDoc); @@ -120,6 +132,15 @@ Model_Document::Model_Document(const int theID, const std::string theKind) myDoc->CommitCommand(); } +Model_Document::~Model_Document() +{ + if (!myDoc.IsNull()) + { + myDoc->ClearUndos(); + myDoc->ClearRedos(); + } +} + void Model_Document::setThis(DocumentPtr theDoc) { myObjs->setOwner(theDoc); @@ -222,24 +243,20 @@ static void updateShapesFromRoot(const TDF_Label theThisAccess, const TDF_Label } // LCOV_EXCL_STOP -bool Model_Document::load(const char* theDirName, const char* theFileName, DocumentPtr theThis) +static bool loadDocument(Handle(Model_Application) theApp, + Handle(TDocStd_Document)& theDoc, + const TCollection_ExtendedString& theFilename) { - Handle(Model_Application) anApp = Model_Application::getApplication(); - if (isRoot()) { - anApp->setLoadPath(theDirName); - } - TCollection_ExtendedString aPath(DocFileName(theDirName, theFileName)); - PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1; - Handle(TDocStd_Document) aLoaded; + PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus)-1; try { - aStatus = anApp->Open(aPath, aLoaded); + aStatus = theApp->Open(theFilename, theDoc); } catch (Standard_Failure const& anException) { Events_InfoMessage("Model_Document", "Exception in opening of document: %1").arg(anException.GetMessageString()).send(); return false; } - bool isError = aStatus != PCDM_RS_OK; - if (isError) { + bool isOk = aStatus == PCDM_RS_OK; + if (!isOk) { // LCOV_EXCL_START switch (aStatus) { case PCDM_RS_UnknownDocument: @@ -297,9 +314,24 @@ bool Model_Document::load(const char* theDirName, const char* theFileName, Docum } // LCOV_EXCL_STOP } + return isOk; +} + +bool Model_Document::load(const char* theDirName, const char* theFileName, DocumentPtr theThis) +{ + Handle(Model_Application) anApp = Model_Application::getApplication(); + if (isRoot()) { + anApp->setLoadPath(theDirName); + } + TCollection_ExtendedString aPath(DocFileName(theDirName, theFileName)); + Handle(TDocStd_Document) aLoaded; + bool isOk = loadDocument(anApp, aLoaded, aPath); + std::shared_ptr aSession = std::dynamic_pointer_cast(Model_Session::get()); - if (!isError) { + if (isOk) { + // keep handle to avoid destruction of the document until myObjs works on it + Handle(TDocStd_Document) anOldDoc = myDoc; myDoc = aLoaded; myDoc->SetUndoLimit(UNDO_LIMIT); @@ -308,6 +340,9 @@ bool Model_Document::load(const char* theDirName, const char* theFileName, Docum aSession->setCheckTransactions(false); if (myObjs) delete myObjs; + anOldDoc->ClearRedos(); + anOldDoc->ClearUndos(); + anOldDoc.Nullify(); myObjs = new Model_Objects(myDoc->Main()); // synchronization is inside myObjs->setOwner(theThis); // update the current features status @@ -334,7 +369,127 @@ bool Model_Document::load(const char* theDirName, const char* theFileName, Docum } else { // open failed, but new document was created to work with it: inform the model aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false); } - return !isError; + return isOk; +} + +bool Model_Document::importPart(const char* theFileName, + std::list >& theImported, + bool theCheckOnly) +{ + Handle(Model_Application) anApp = Model_Application::getApplication(); + TCollection_ExtendedString aFormat; + if (!anApp->Format(theFileName, aFormat)) + return false; + + Handle(TDocStd_Document) aTempDoc; + bool isOk = loadDocument(anApp, aTempDoc, theFileName); + + if (isOk && theCheckOnly) { + // verify all features are applicable for the current document type (e.g. PartSet) + std::shared_ptr aSession = + std::dynamic_pointer_cast(ModelAPI_Session::get()); + for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More() && isOk; anIt.Next()) { + TDF_Label aCurrentLab = anIt.Value(); + Handle(TDataStd_Comment) aFeatureID; + TDF_Label aNewFeatuerLab; + if (aCurrentLab.FindAttribute(TDataStd_Comment::GetID(), aFeatureID)) { + TCollection_AsciiString anID(aFeatureID->Get()); + std::string aFeatureKind(anID.ToCString()); + if (aSession->myPlugins.find(aFeatureKind) != aSession->myPlugins.end()) { + std::string& aDocKind = aSession->myPlugins[aFeatureKind].second; + isOk = aDocKind.empty() || aDocKind == kind(); + } + } + } + } + + if (isOk && !theCheckOnly) { + // copy features from the temporary document to the current + Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable(); + // add to relocation table source root label to the destination label because + // sometimes there could be a reference to root (issue 3267 on import part + // with sketch with removed features) + aRelocTable->SetRelocation(aTempDoc->Main().Root(), myDoc->Main().Root()); + TDF_LabelList anAllNewFeatures; + // Perform the copying twice for correct references: + // 1. copy labels hierarchy and fill the relocation table + for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More(); anIt.Next()) { + TDF_Label aCurrentLab = anIt.Value(); + Handle(TDataStd_Comment) aFeatureID; + TDF_Label aNewFeatuerLab; + if (aCurrentLab.FindAttribute(TDataStd_Comment::GetID(), aFeatureID)) { + TCollection_AsciiString anID(aFeatureID->Get()); + FeaturePtr aNewFeature = addFeature(anID.ToCString()); + std::shared_ptr aData = + std::dynamic_pointer_cast(aNewFeature->data()); + aNewFeatuerLab = aData->label().Father(); + Model_Tools::copyLabels(aCurrentLab, aNewFeatuerLab, aRelocTable); + theImported.push_back(aNewFeature); + } + anAllNewFeatures.Append(aNewFeatuerLab); + } + // 2. copy attributes + std::set aCoordinateLabels; + Model_Tools::labelsOfCoordinates(aCoordinateLabels, aRelocTable); + TDF_ListIteratorOfLabelList aNewIt(anAllNewFeatures); + for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More(); anIt.Next()) { + TDF_Label aCurrentLab = anIt.Value(); + TDF_Label aFeatureLab = aNewIt.Value(); + if (aFeatureLab.IsNull()) + anAllNewFeatures.Remove(aNewIt); + else { + Model_Tools::copyAttrsAndKeepRefsToCoordinates( + aCurrentLab, aFeatureLab, aCoordinateLabels, aRelocTable); + aNewIt.Next(); + } + } + + myObjs->synchronizeFeatures(anAllNewFeatures, true, false, false, true); + } + + if (anApp->CanClose(aTempDoc) == CDM_CCS_OK) + anApp->Close(aTempDoc); + return isOk; +} + +static bool saveDocument(Handle(Model_Application) theApp, + Handle(TDocStd_Document) theDoc, + const TCollection_ExtendedString& theFilename) +{ + PCDM_StoreStatus aStatus; + try { + // create the directory to save the document + OSD_Path aPathToFile = UTL::Path(theFilename); + aPathToFile.SetName(""); + aPathToFile.SetExtension(""); + OSD_Directory aBaseDir(aPathToFile); + if (aPathToFile.TrekLength() != 0 && !aBaseDir.Exists()) + aBaseDir.Build(OSD_Protection()); + // save the document + aStatus = theApp->SaveAs(theDoc, theFilename); + } + catch (Standard_Failure const& anException) { + Events_InfoMessage("Model_Document", + "Exception in saving of document: %1").arg(anException.GetMessageString()).send(); + return false; + } + bool isDone = aStatus == PCDM_SS_OK || aStatus == PCDM_SS_No_Obj; + if (!isDone) { + switch (aStatus) { + case PCDM_SS_DriverFailure: + Events_InfoMessage("Model_Document", + "Can not save document: save driver-library failure").send(); + break; + case PCDM_SS_WriteFailure: + Events_InfoMessage("Model_Document", "Can not save document: file writing failure").send(); + break; + case PCDM_SS_Failure: + default: + Events_InfoMessage("Model_Document", "Can not save document").send(); + break; + } + } + return isDone; } bool Model_Document::save( @@ -375,34 +530,7 @@ bool Model_Document::save( } // filename in the dir is id of document inside of the given directory TCollection_ExtendedString aPath(DocFileName(theDirName, theFileName)); - PCDM_StoreStatus aStatus; - try { - aStatus = anApp->SaveAs(myDoc, aPath); - } catch (Standard_Failure const& anException) { - Events_InfoMessage("Model_Document", - "Exception in saving of document: %1").arg(anException.GetMessageString()).send(); - if (aWasCurrent.get()) { // return the current feature to the initial position - setCurrentFeature(aWasCurrent, false); - aSession->setCheckTransactions(true); - } - return false; - } - bool isDone = aStatus == PCDM_SS_OK || aStatus == PCDM_SS_No_Obj; - if (!isDone) { - switch (aStatus) { - case PCDM_SS_DriverFailure: - Events_InfoMessage("Model_Document", - "Can not save document: save driver-library failure").send(); - break; - case PCDM_SS_WriteFailure: - Events_InfoMessage("Model_Document", "Can not save document: file writing failure").send(); - break; - case PCDM_SS_Failure: - default: - Events_InfoMessage("Model_Document", "Can not save document").send(); - break; - } - } + bool isDone = saveDocument(anApp, myDoc, aPath); if (aWasCurrent.get()) { // return the current feature to the initial position setCurrentFeature(aWasCurrent, false); @@ -420,12 +548,12 @@ bool Model_Document::save( ResultPartPtr aPart = std::dynamic_pointer_cast(*aPartRes); if (!aPart->isActivated()) { // copy not-activated document that is not in the memory - std::string aDocName = aPart->data()->name(); + std::string aDocName = Locale::Convert::toString(aPart->data()->name()); if (!aDocName.empty()) { // just copy file TCollection_AsciiString aSubPath(DocFileName(anApp->loadPath().c_str(), aDocName)); - OSD_Path aPath(aSubPath); - OSD_File aFile(aPath); + OSD_Path aCopyPath(aSubPath); + OSD_File aFile(aCopyPath); if (aFile.Exists()) { TCollection_AsciiString aDestinationDir(DocFileName(theDirName, aDocName)); OSD_Path aDestination(aDestinationDir); @@ -437,14 +565,53 @@ bool Model_Document::save( } } } else { // simply save opened document + std::string aDocName = Locale::Convert::toString(aPart->data()->name()); isDone = std::dynamic_pointer_cast(aPart->partDoc())-> - save(theDirName, aPart->data()->name().c_str(), theResults); + save(theDirName, aDocName.c_str(), theResults); } } } return isDone; } +bool Model_Document::save(const char* theFilename, + const std::list& theExportFeatures) const +{ + Handle(Model_Application) anApp = Model_Application::getApplication(); + TCollection_ExtendedString aFormat; + if (!anApp->Format(theFilename, aFormat)) + return false; + + Handle(TDocStd_Document) aTempDoc = new TDocStd_Document(aFormat); + TDF_Label aMain = aTempDoc->Main(); + + Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable(); + std::list::const_iterator anIt = theExportFeatures.begin(); + // Perform the copying twice for correct references: + // 1. copy labels hierarchy and fill the relocation table + for (; anIt != theExportFeatures.end(); ++anIt) { + TDF_Label aFeatureLab = aMain.NewChild(); + std::shared_ptr aData = std::dynamic_pointer_cast((*anIt)->data()); + Model_Tools::copyLabels(aData->label().Father(), aFeatureLab, aRelocTable); + } + // 2. copy attributes + std::set aCoordinateLabels; + Model_Tools::labelsOfCoordinates(aCoordinateLabels, aRelocTable); + TDF_ChildIterator aChildIt(aMain); + for (anIt = theExportFeatures.begin(); anIt != theExportFeatures.end(); ++anIt) { + TDF_Label aFeatureLab = aChildIt.Value(); + std::shared_ptr aData = std::dynamic_pointer_cast((*anIt)->data()); + Model_Tools::copyAttrsAndKeepRefsToCoordinates( + aData->label().Father(), aFeatureLab, aCoordinateLabels, aRelocTable); + aChildIt.Next(); + } + + bool isDone = saveDocument(anApp, aTempDoc, theFilename); + if (aTempDoc->CanClose() == CDM_CCS_OK) + aTempDoc->Close(); + return isDone; +} + void Model_Document::close(const bool theForever) { std::shared_ptr aPM = Model_Session::get(); @@ -622,7 +789,7 @@ static bool isEmptyTransaction(const Handle(TDocStd_Document)& theDoc) { aDelta = theDoc->GetUndos().Last(); TDF_LabelList aDeltaList; aDelta->Labels(aDeltaList); // it clears list, so, use new one and then append to the result - for(TDF_ListIteratorOfLabelList aListIter(aDeltaList); aListIter.More(); aListIter.Next()) { + if (!aDeltaList.IsEmpty()) { return false; } // add also label of the modified attributes @@ -850,7 +1017,7 @@ bool Model_Document::isOperation() const bool Model_Document::isModified() { // is modified if at least one operation was committed and not undone - return myTransactions.size() != myTransactionSave || isOperation(); + return (int)myTransactions.size() != myTransactionSave || isOperation(); } bool Model_Document::canUndo() @@ -893,9 +1060,10 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron myDoc->Undo(); } + std::set aSubs; if (theWithSubs) { // undo for all subs - const std::set aSubs = subDocuments(); + aSubs = subDocuments(); std::set::iterator aSubIter = aSubs.begin(); for (; aSubIter != aSubs.end(); aSubIter++) { if (!subDoc(*aSubIter)->myObjs) @@ -908,6 +1076,19 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron myObjs->synchronizeFeatures(aDeltaLabels, true, false, false, isRoot()); // update the current features status setCurrentFeature(currentFeature(false), false); + + if (theWithSubs) { + // undo for all subs + const std::set aNewSubs = subDocuments(); + std::set::iterator aNewSubIter = aNewSubs.begin(); + for (; aNewSubIter != aNewSubs.end(); aNewSubIter++) { + // synchronize only newly appeared documents + if (!subDoc(*aNewSubIter)->myObjs || aSubs.find(*aNewSubIter) != aSubs.end()) + continue; + TDF_LabelList anEmptyDeltas; + subDoc(*aNewSubIter)->myObjs->synchronizeFeatures(anEmptyDeltas, true, false, true, true); + } + } } } @@ -994,6 +1175,8 @@ FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurre { std::shared_ptr aSession = std::dynamic_pointer_cast(ModelAPI_Session::get()); + if (!aSession->hasModuleDocument() || !myObjs) + return FeaturePtr(); // this may be on close of the document FeaturePtr aFeature = aSession->createFeature(theID, this); if (!aFeature) return aFeature; @@ -1026,6 +1209,15 @@ FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurre } } } + // #2861,3029: 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 if (theMakeCurrent) // after all this feature stays in the document, so make it current @@ -1076,7 +1268,7 @@ static bool isSub(const CompositeFeaturePtr theMain, const FeaturePtr theSub) { return isSub(theMain, aParent); } -void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) +void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis, const bool theSplit) { bool aCurrentUp = theMoved == currentFeature(false); if (aCurrentUp) { @@ -1100,13 +1292,26 @@ void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) } while (aSub.get()); } + AttributeSelectionListPtr aMovedList; + if (theMoved->getKind() == "Group") { + aMovedList = theMoved->selectionList("group_list"); + if (aMovedList.get()) + aMovedList->setMakeCopy(true); + } myObjs->moveFeature(theMoved, anAfterThisSub); + + if (theSplit) { // split the group into sub-features + theMoved->customAction("split"); + } + if (aCurrentUp) { // make the moved feature enabled or disabled due to the real status setCurrentFeature(currentFeature(false), false); } else if (theAfterThis == currentFeature(false) || anAfterThisSub == currentFeature(false)) { // must be after move to make enabled all features which are before theMoved setCurrentFeature(theMoved, true); } + if (aMovedList.get()) + aMovedList->setMakeCopy(false); } void Model_Document::updateHistory(const std::shared_ptr theObject) @@ -1151,7 +1356,7 @@ ObjectPtr Model_Document::object(const std::string& theGroupID, } std::shared_ptr Model_Document::objectByName( - const std::string& theGroupID, const std::string& theName) + const std::string& theGroupID, const std::wstring& theName) { return myObjs->objectByName(theGroupID, theName); } @@ -1236,6 +1441,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()) { @@ -1317,6 +1534,9 @@ void Model_Document::setCurrentFeature( myIsSetCurrentFeature = false; // unblock the flush signals and up them after this aLoop->activateFlushes(isActive); + + static Events_ID kUpdatedSel = aLoop->eventByName(EVENT_UPDATE_SELECTION); + aLoop->flush(kUpdatedSel); } void Model_Document::setCurrentFeatureUp() @@ -1461,9 +1681,9 @@ ResultPtr Model_Document::resultByLab(const TDF_Label& theLab) return ResultPtr(); // not found } -void Model_Document::addNamingName(const TDF_Label theLabel, std::string theName) +void Model_Document::addNamingName(const TDF_Label theLabel, std::wstring theName) { - std::map >::iterator aFind = myNamingNames.find(theName); + std::map >::iterator aFind = myNamingNames.find(theName); if (aFind != myNamingNames.end()) { // to avoid duplicate-labels // to keep correct order in spite of history line management @@ -1495,11 +1715,11 @@ void Model_Document::addNamingName(const TDF_Label theLabel, std::string theName myNamingNames[theName].push_back(theLabel); } -void Model_Document::changeNamingName(const std::string theOldName, - const std::string theNewName, +void Model_Document::changeNamingName(const std::wstring theOldName, + const std::wstring theNewName, const TDF_Label& theLabel) { - std::map >::iterator aFind = myNamingNames.find(theOldName); + std::map >::iterator aFind = myNamingNames.find(theOldName); if (aFind != myNamingNames.end()) { std::list::iterator aLabIter = aFind->second.begin(); for(; aLabIter != aFind->second.end(); aLabIter++) { @@ -1514,9 +1734,9 @@ void Model_Document::changeNamingName(const std::string theOldName, TDF_ChildIDIterator aChild(theLabel, TDataStd_Name::GetID()); for(; aChild.More(); aChild.Next()) { Handle(TDataStd_Name) aSubName = Handle(TDataStd_Name)::DownCast(aChild.Value()); - std::string aName = TCollection_AsciiString(aSubName->Get()).ToCString(); + std::wstring aName = Locale::Convert::toWString(aSubName->Get().ToExtString()); if (aName.find(theOldName) == 0) { // started from parent name - std::string aNewSubName = theNewName + aName.substr(theNewName.size()); + std::wstring aNewSubName = theNewName + aName.substr(theOldName.size()); changeNamingName(aName, aNewSubName, aSubName->Label()); aSubName->Set(aNewSubName.c_str()); } @@ -1527,9 +1747,55 @@ void Model_Document::changeNamingName(const std::string theOldName, } } -TDF_Label Model_Document::findNamingName(std::string theName, ResultPtr theContext) +// returns true if names consist of the same sub-elements but with different order. +// Sub-elements are separated by "-" symbol. First part must be "Face", second at the same place. +static bool IsExchangedName(const TCollection_ExtendedString& theName1, + const TCollection_ExtendedString& theName2) { - std::map >::iterator aFind = myNamingNames.find(theName); + static const TCollection_ExtendedString aSepStr("-"); + static const Standard_ExtString aSep = aSepStr.ToExtString(); + static const TCollection_ExtendedString aWireTail("_wire"); + if (theName1.Token(aSep, 1) != "Face" || theName2.Token(aSep, 1) != "Face") + return false; + if (theName1.Token(aSep, 2) != theName2.Token(aSep, 2)) + return false; + // Collect Map of the sub-elements of the first name + NCollection_Map aSubsMap; + TCollection_ExtendedString aWireSuffix; + int a = 3; + for (; true ; a++) { + TCollection_ExtendedString aToken = theName1.Token(aSep, a); + if (aToken.IsEmpty()) + break; + int aTailPos = aToken.Search(aWireTail); + if (aTailPos > 0) { + aWireSuffix = aToken.Split(aTailPos - 1); + } + aSubsMap.Add(aToken); + } + // check all subs in the second name are in the map + for (int a2 = 3; true; a2++) { + TCollection_ExtendedString aToken = theName2.Token(aSep, a2); + if (aToken.IsEmpty()) { + if (a2 != a) // number of sub-elements is not equal + return false; + break; + } + int aTailPos = aToken.Search(aWireTail); + if (aTailPos > 0) { + TCollection_ExtendedString aSuffix = aToken.Split(aTailPos - 1); + if (aWireSuffix != aSuffix) + return false; + } + if (!aSubsMap.Contains(aToken)) + return false; + } + return true; +} + +TDF_Label Model_Document::findNamingName(std::wstring theName, ResultPtr theContext) +{ + std::map >::iterator aFind = myNamingNames.find(theName); if (aFind != myNamingNames.end()) { std::list::reverse_iterator aLabIter = aFind->second.rbegin(); for(; aLabIter != aFind->second.rend(); aLabIter++) { @@ -1542,9 +1808,9 @@ TDF_Label Model_Document::findNamingName(std::string theName, ResultPtr theConte return *(aFind->second.rbegin()); // no more variants, so, return the last } // not found exact name, try to find by sub-components - std::string::size_type aSlash = theName.rfind('/'); - if (aSlash != std::string::npos) { - std::string anObjName = theName.substr(0, aSlash); + std::wstring::size_type aSlash = theName.rfind(L'/'); + if (aSlash != std::wstring::npos) { + std::wstring anObjName = theName.substr(0, aSlash); aFind = myNamingNames.find(anObjName); if (aFind != myNamingNames.end()) { TCollection_ExtendedString aSubName(theName.substr(aSlash + 1).c_str()); @@ -1558,13 +1824,19 @@ TDF_Label Model_Document::findNamingName(std::string theName, ResultPtr theConte } // copy aSubName to avoid incorrect further processing after its suffix cutting TCollection_ExtendedString aSubNameCopy(aSubName); + TDF_Label aFaceLabelWithExchangedSubs; // check also exchanged sub-elements of the name // searching sub-labels with this name TDF_ChildIDIterator aNamesIter(*aLabIter, TDataStd_Name::GetID(), Standard_True); for(; aNamesIter.More(); aNamesIter.Next()) { Handle(TDataStd_Name) aName = Handle(TDataStd_Name)::DownCast(aNamesIter.Value()); if (aName->Get() == aSubNameCopy) return aName->Label(); + if (aName->Get().Length() == aSubNameCopy.Length() && + IsExchangedName(aName->Get(), aSubNameCopy)) + aFaceLabelWithExchangedSubs = aName->Label(); } + if (!aFaceLabelWithExchangedSubs.IsNull()) + return aFaceLabelWithExchangedSubs; // If not found child label with the exact sub-name, then try to find compound with // such sub-name without suffix. Standard_Integer aSuffixPos = aSubNameCopy.SearchFromEnd('_'); @@ -1634,7 +1906,7 @@ bool Model_Document::isLaterByDep(FeaturePtr theThis, FeaturePtr theOther) { int Model_Document::numberOfNameInHistory( const ObjectPtr& theNameObject, const TDF_Label& theStartFrom) { - std::map >::iterator aFind = + std::map >::iterator aFind = myNamingNames.find(theNameObject->data()->name()); if (aFind == myNamingNames.end() || aFind->second.size() < 2) { return 1; // no need to specify the name by additional identifiers @@ -1672,10 +1944,10 @@ int Model_Document::numberOfNameInHistory( } ResultPtr Model_Document::findByName( - std::string& theName, std::string& theSubShapeName, bool& theUniqueContext) + std::wstring& theName, std::wstring& theSubShapeName, bool& theUniqueContext) { int aNumInHistory = 0; - std::string aName = theName; + std::wstring aName = theName; ResultPtr aRes = myObjs->findByName(aName); theUniqueContext = !(aRes.get() && myNamingNames.find(aName) != myNamingNames.end()); while(!aRes.get() && aName[0] == '_') { // this may be theContext with the history index @@ -1684,8 +1956,8 @@ ResultPtr Model_Document::findByName( aRes = myObjs->findByName(aName); } if (aNumInHistory) { - std::map >::iterator aFind = myNamingNames.find(aName); - if (aFind != myNamingNames.end() && aFind->second.size() > aNumInHistory) { + std::map >::iterator aFind = myNamingNames.find(aName); + if (aFind != myNamingNames.end() && (int)aFind->second.size() > aNumInHistory) { std::list::reverse_iterator aLibIt = aFind->second.rbegin(); for(; aNumInHistory != 0; aNumInHistory--) aLibIt++; @@ -1829,7 +2101,7 @@ AttributeSelectionListPtr Model_Document::selectionInPartFeature() aData->setObject(mySelectionFeature); mySelectionFeature->setDoc(myObjs->owner()); mySelectionFeature->setData(aData); - std::string aName = id() + "_Part"; + std::wstring aName = id() + L"_Part"; mySelectionFeature->data()->setName(aName); mySelectionFeature->setDoc(myObjs->owner()); mySelectionFeature->initAttributes(); @@ -2029,6 +2301,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; @@ -2045,6 +2327,8 @@ void Model_Document::appendTransactionToPrevious() { Transaction anAppended = myTransactions.back(); myTransactions.pop_back(); + if (!myNestedNum.empty()) + (*myNestedNum.rbegin())--; if (!myTransactions.empty()) { // if it is empty, just forget the appended myTransactions.back().myOCAFNum += anAppended.myOCAFNum; }