X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Objects.cpp;h=b4e516cd64e75305d523ad0c750635d14376c1f0;hb=a0277ef450c038f1d9379265dd129dcf8397dec2;hp=1da563d21b5f65b8e6390e88addef88770156ef9;hpb=c8fd356b4c1e7fb116023cfc9bc4ac87915607b0;p=modules%2Fshaper.git diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 1da563d21..b4e516cd6 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -60,6 +60,22 @@ static const std::string& groupNameFoldering(const std::string& theGroupID, return theGroupID; } +// Check theFeature is a first or last feature in folder and return this folder +static FolderPtr inFolder(const FeaturePtr& theFeature, const std::string& theFolderAttr) +{ + const std::set& aRefs = theFeature->data()->refsToMe(); + for (std::set::iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) { + if ((*anIt)->id() != theFolderAttr) + continue; + + ObjectPtr anOwner = (*anIt)->owner(); + FolderPtr aFolder = std::dynamic_pointer_cast(anOwner); + if (aFolder.get()) + return aFolder; + } + return FolderPtr(); +} + static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, results) @@ -160,12 +176,24 @@ void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterT // store feature in the features array: before "initData" because in macro features // in initData it creates new features, appeared later than this TDF_Label aPrevFeateureLab; + FolderPtr aParentFolder; 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(); } + // Check if the previous feature is the last feature in a folder, + // then the folder should be updated to contain additional feature. + // Macro features are not stored in folder. + if (!theFeature->isMacro()) { + // If the last feature is a sub-feature of composite, use parent feature + // to check belonging to a folder. + FeaturePtr afterThis = ModelAPI_Tools::compositeOwner(theAfterThis); + if (!afterThis) + afterThis = theAfterThis; + aParentFolder = inFolder(afterThis, ModelAPI_Folder::LAST_FEATURE_ID()); + } } AddToRefArray(aFeaturesLab, aFeatureLab, aPrevFeateureLab); @@ -183,6 +211,12 @@ void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterT // must be after binding to the map because of "Box" macro feature that // creates other features in "initData" initData(theFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS); + // put feature to the end of folder if it is added while + // the history line is set to the last feature from the folder + if (aParentFolder) { + aParentFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID())->setValue(theFeature); + updateHistory(ModelAPI_Folder::group()); + } // event: feature is added, mist be before "initData" to update OB correctly on Duplicate: // first new part, then the content static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); @@ -281,6 +315,8 @@ void Model_Objects::removeFeature(FeaturePtr theFeature) aComposite->removeFeature(theFeature); } } + // remove feature from folder + removeFromFolder(std::list(1, theFeature)); // this must be before erase since theFeature erasing removes all information about // the feature results and groups of results // To reproduce: create sketch, extrusion, remove sketch => constructions tree is not updated @@ -451,7 +487,7 @@ void Model_Objects::createHistory(const std::string& theGroupID) } else { // it may be a folder - ObjectPtr aFolder = folder(aRefs->Value(a)); + const ObjectPtr& aFolder = folder(aRefs->Value(a)); if (aFolder.get()) { // store folder information for the Features group only if (isFeature || isFolder) { @@ -499,11 +535,12 @@ void Model_Objects::updateHistory(const std::string theGroup) } } -ObjectPtr Model_Objects::folder(TDF_Label theLabel) const +const ObjectPtr& Model_Objects::folder(TDF_Label theLabel) const { if (myFolders.IsBound(theLabel)) return myFolders.Find(theLabel); - return ObjectPtr(); + static ObjectPtr anEmptyResult; + return anEmptyResult; } FeaturePtr Model_Objects::feature(TDF_Label theLabel) const @@ -564,6 +601,9 @@ ObjectPtr Model_Objects::object(const std::string& theGroupID, return ObjectPtr(); createHistory(theGroupID); const std::string& aGroupID = groupNameFoldering(theGroupID, theAllowFolder); + const std::vector& aVec = myHistory[theGroupID]; + //if (aVec.size() <= theIndex) + // return aVec[aVec.size() - 1]; // too high index requested (to avoid crash in #2360) return aGroupID.empty() ? myHistory[theGroupID][theIndex] : myHistory[aGroupID][theIndex]; } @@ -784,7 +824,7 @@ void Model_Objects::synchronizeFeatures( TDF_Label& aFeatureLab = anUpdatedIter.Value(); while(aFeatureLab.Depth() > 3) aFeatureLab = aFeatureLab.Father(); - if (myFeatures.IsBound(aFeatureLab)) + if (myFeatures.IsBound(aFeatureLab) || myFolders.IsBound(aFeatureLab)) anUpdatedMap.Add(aFeatureLab); } @@ -998,6 +1038,35 @@ void Model_Objects::synchronizeBackRefsForObject(const std::set& t } else aCurrentIter++; } } + // for the last feature in the folder, check if it is a sub-feature, + // then refer the folder to a top-level parent composite feature + const std::set& aRefs = aData->refsToMe(); + std::set::iterator anIt = aRefs.begin(); + for (; anIt != aRefs.end(); ++anIt) + if ((*anIt)->id() == ModelAPI_Folder::LAST_FEATURE_ID()) + break; + if (anIt != aRefs.end()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature) { + CompositeFeaturePtr aParent; + CompositeFeaturePtr aGrandParent = ModelAPI_Tools::compositeOwner(aFeature); + do { + aParent = aGrandParent; + if (aGrandParent) + aGrandParent = ModelAPI_Tools::compositeOwner(aParent); + } while (aGrandParent.get()); + if (aParent) { + ObjectPtr aFolder = (*anIt)->owner(); + // remove reference from the current feature + aData->removeBackReference(aFolder, ModelAPI_Folder::LAST_FEATURE_ID()); + // set reference to a top-level parent + aFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID())->setValue(aParent); + std::shared_ptr aParentData = + std::dynamic_pointer_cast(aParent->data()); + aParentData->addBackReference(aFolder, ModelAPI_Folder::LAST_FEATURE_ID()); + } + } + } aData->updateConcealmentFlag(); } @@ -1415,8 +1484,9 @@ std::shared_ptr Model_Objects::findFolder( continue; } - aFoundFolder = std::dynamic_pointer_cast(folder(aCurLabel)); - if (aFoundFolder) { + const ObjectPtr& aFolderObj = folder(aCurLabel); + if (aFolderObj.get()) { + aFoundFolder = std::dynamic_pointer_cast(aFolderObj); AttributeReferencePtr aLastFeatAttr = aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID()); if (aLastFeatAttr) { @@ -1544,21 +1614,6 @@ bool Model_Objects::moveToFolder( return true; } -static FolderPtr inFolder(const FeaturePtr& theFeature, const std::string& theFolderAttr) -{ - const std::set& aRefs = theFeature->data()->refsToMe(); - for (std::set::iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) { - if ((*anIt)->id() != theFolderAttr) - continue; - - ObjectPtr anOwner = (*anIt)->owner(); - FolderPtr aFolder = std::dynamic_pointer_cast(anOwner); - if (aFolder.get()) - return aFolder; - } - return FolderPtr(); -} - static FolderPtr isExtractionCorrect(const FolderPtr& theFirstFeatureFolder, const FolderPtr& theLastFeatureFolder, bool& isExtractBefore) @@ -1679,19 +1734,31 @@ FolderPtr Model_Objects::findContainingFolder(const FeaturePtr& theFeature, int& for (int aRefIndex = aRefs->Lower(); aRefIndex <= aRefs->Upper(); ++aRefIndex) { TDF_Label aCurLabel = aRefs->Value(aRefIndex); - if (isSkippedFeature(feature(aCurLabel))) - continue; if (aFoundFolder) ++theIndexInFolder; - if (aCurLabel == aLabelToFind) // the feature is reached + if (aCurLabel == aLabelToFind) { // the feature is reached + if (aFoundFolder) { + if (isSkippedFeature(theFeature)) { + theIndexInFolder = -1; + return FolderPtr(); + } + // decrease the index of the feature in the folder by the number of skipped features + for (int anIndex = theIndexInFolder - 1; anIndex > 0; anIndex--) { + aCurLabel = aRefs->Value(aRefIndex - anIndex); + if (isSkippedFeature(feature(aCurLabel))) + theIndexInFolder--; + } + } return aFoundFolder; + } if (!aFoundFolder) { // if the current label refers to a folder, feel all necessary data - aFoundFolder = std::dynamic_pointer_cast(folder(aCurLabel)); - if (aFoundFolder) { + const ObjectPtr& aFolderObj = folder(aCurLabel); + if (aFolderObj.get()) { + aFoundFolder = std::dynamic_pointer_cast(aFolderObj); theIndexInFolder = -1; AttributeReferencePtr aLastRef = @@ -1874,9 +1941,16 @@ FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theRever std::shared_ptr aData = std::static_pointer_cast(theCurrent->data()); if (aData.get() && aData->isValid()) { TDF_Label aFeatureLabel = aData->label().Father(); - TDF_Label aNextLabel = nextLabel(aFeatureLabel, theReverse); - if (!aNextLabel.IsNull()) - return feature(aNextLabel); + do { + TDF_Label aNextLabel = nextLabel(aFeatureLabel, theReverse); + if (aNextLabel.IsNull()) + break; // last or something is wrong + FeaturePtr aFound = feature(aNextLabel); + if (aFound) + return aFound; // the feature is found + // if the next label is a folder, skip it + aFeatureLabel = folder(aNextLabel).get() ? aNextLabel : TDF_Label(); + } while (!aFeatureLabel.IsNull()); } return FeaturePtr(); // not found, last, or something is wrong } @@ -1894,6 +1968,11 @@ FeaturePtr Model_Objects::lastFeature() { Handle(TDataStd_ReferenceArray) aRefs; if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { + FeaturePtr aLast = feature(aRefs->Value(aRefs->Upper())); + if (!aLast.get() && aRefs->Length() != 0) { // erase the invalid feature from the array + RemoveFromRefArray(featuresLabel(), aRefs->Value(aRefs->Upper())); + return lastFeature(); // try once again, after the last was removed + } return feature(aRefs->Value(aRefs->Upper())); } return FeaturePtr(); // no features at all