From: azv Date: Fri, 24 Nov 2017 11:30:03 +0000 (+0300) Subject: Methods to remove features from folders (Task 2.3. Ability to put consecutive Feature... X-Git-Tag: V_2.10.0RC~123^2~21^2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=e333d88c6c87b8e41f127aa55b1583a98b683bff;p=modules%2Fshaper.git Methods to remove features from folders (Task 2.3. Ability to put consecutive Features in a folder) --- diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 9911a7964..49bca1d27 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -468,9 +468,9 @@ void Model_Data::eraseBackReferences() aRes->setIsConcealed(false); } -void Model_Data::removeBackReference(FeaturePtr theFeature, std::string theAttrID) +void Model_Data::removeBackReference(ObjectPtr theObject, std::string theAttrID) { - AttributePtr anAttribute = theFeature->data()->attribute(theAttrID); + AttributePtr anAttribute = theObject->data()->attribute(theAttrID); removeBackReference(anAttribute); } @@ -492,10 +492,7 @@ void Model_Data::removeBackReference(AttributePtr theAttr) void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID, const bool theApplyConcealment) { - // it is possible to add the same attribute twice: may be last time the owner was not Stable... - AttributePtr anAttribute = theFeature->data()->attribute(theAttrID); - if (myRefsToMe.find(anAttribute) == myRefsToMe.end()) - myRefsToMe.insert(theFeature->data()->attribute(theAttrID)); + addBackReference(ObjectPtr(theFeature), theAttrID); if (theApplyConcealment && theFeature->isStable() && ModelAPI_Session::get()->validators()->isConcealed(theFeature->getKind(), theAttrID)) { @@ -510,6 +507,14 @@ void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID, } } +void Model_Data::addBackReference(ObjectPtr theObject, std::string theAttrID) +{ + // it is possible to add the same attribute twice: may be last time the owner was not Stable... + AttributePtr anAttribute = theObject->data()->attribute(theAttrID); + if (myRefsToMe.find(anAttribute) == myRefsToMe.end()) + myRefsToMe.insert(anAttribute); +} + void Model_Data::updateConcealmentFlag() { std::set::iterator aRefsIter = myRefsToMe.begin(); diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index 186cfefc2..72875fc5a 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -271,7 +272,7 @@ private: /// Removes a back reference (with identifier which attribute references to this object) /// \param theFeature feature referenced to this /// \param theAttrID identifier of the attribute that is references from theFeature to this - void removeBackReference(FeaturePtr theFeature, std::string theAttrID); + void removeBackReference(ObjectPtr theObject, std::string theAttrID); /// Removes a back reference (by the attribute) /// \param theAttr the referenced attribute void removeBackReference(AttributePtr theAttr); @@ -281,6 +282,10 @@ private: /// \param theApplyConcealment applies consealment flag changes void addBackReference(FeaturePtr theFeature, std::string theAttrID, const bool theApplyConcealment = true); + /// Adds a back reference to an object + /// \param theObject object referenced to this + /// \param theAttrID identifier of the attribute that is references from theFolder to this + void addBackReference(ObjectPtr theObject, std::string theAttrID); /// Makes the concealment flag up to date for this object-owner. MODEL_EXPORT virtual void updateConcealmentFlag(); @@ -303,11 +308,15 @@ private: /// Without concealment change, it will be done later, on synchronization. #define ADD_BACK_REF(TARGET) \ if (TARGET.get() != NULL) { \ + std::shared_ptr aTargetData = \ + std::dynamic_pointer_cast((TARGET)->data()); \ FeaturePtr anAttributeOwnerFeature = std::dynamic_pointer_cast(owner()); \ - if (anAttributeOwnerFeature.get()) { \ - std::shared_ptr aTargetData = std::dynamic_pointer_cast( \ - (TARGET)->data()); \ + if (anAttributeOwnerFeature.get()) \ aTargetData->addBackReference(anAttributeOwnerFeature, id(), false); \ + else { \ + FolderPtr anAttributeOwnerFolder = std::dynamic_pointer_cast(owner()); \ + if (anAttributeOwnerFolder.get()) \ + aTargetData->addBackReference(anAttributeOwnerFolder, id()); \ } \ } @@ -315,11 +324,15 @@ private: /// Without concealment change, it will be done later, on synchronization. #define REMOVE_BACK_REF(TARGET) \ if (TARGET.get() != NULL) { \ + std::shared_ptr aTargetData = \ + std::dynamic_pointer_cast((TARGET)->data()); \ FeaturePtr anAttOwnerFeature = std::dynamic_pointer_cast(owner()); \ - if (anAttOwnerFeature.get()) { \ - std::shared_ptr aTargetData = std::dynamic_pointer_cast( \ - (TARGET)->data()); \ + if (anAttOwnerFeature.get()) \ aTargetData->removeBackReference(anAttOwnerFeature, id()); \ + else { \ + FolderPtr anAttributeOwnerFolder = std::dynamic_pointer_cast(owner()); \ + if (anAttributeOwnerFolder.get()) \ + aTargetData->removeBackReference(anAttributeOwnerFolder, id()); \ } \ } diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 58a8b6b42..669c6ac1f 100755 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -1289,9 +1289,10 @@ bool Model_Document::moveToFolder( } bool Model_Document::removeFromFolder( - const std::list >& theFeatures) + const std::list >& theFeatures, + const bool theBefore) { - return myObjs->removeFromFolder(theFeatures); + return myObjs->removeFromFolder(theFeatures, theBefore); } std::shared_ptr Model_Document::feature( diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 300c07d61..946025f73 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -228,9 +228,14 @@ class Model_Document : public ModelAPI_Document const std::list >& theFeatures, const std::shared_ptr& theFolder); //! Remove features from the folder + //! \param theFeatures list of features to be removed + //! \param theBefore extract features before the folder (this parameter is applicable only + //! when all features in the folder are taking out, + //! in other cases the direction is taken automatically) //! \return \c true if the features have been moved out MODEL_EXPORT virtual bool removeFromFolder( - const std::list >& theFeatures); + const std::list >& theFeatures, + const bool theBefore = true); ///! 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 diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 4163c0b51..4522d14d8 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -961,6 +961,29 @@ void Model_Objects::synchronizeBackRefsForObject(const std::set& t aData->updateConcealmentFlag(); } +static void collectReferences(std::shared_ptr theData, + std::map >& theRefs) +{ + if (theData.get()) { + std::list > > aRefs; + theData->referencesToObjects(aRefs); + std::list > >::iterator aRefsIt = aRefs.begin(); + for(; aRefsIt != aRefs.end(); aRefsIt++) { + std::list::iterator aRefTo = aRefsIt->second.begin(); + for(; aRefTo != aRefsIt->second.end(); aRefTo++) { + if (*aRefTo) { + std::map >::iterator aFound = theRefs.find(*aRefTo); + if (aFound == theRefs.end()) { + theRefs[*aRefTo] = std::set(); + aFound = theRefs.find(*aRefTo); + } + aFound->second.insert(theData->attribute(aRefsIt->first)); + } + } + } + } +} + void Model_Objects::synchronizeBackRefs() { // collect all back references in the separated container: to update everything at once, @@ -971,25 +994,12 @@ void Model_Objects::synchronizeBackRefs() 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.get()) { - std::list > > aRefs; - aFData->referencesToObjects(aRefs); - std::list > >::iterator aRefsIt = aRefs.begin(); - for(; aRefsIt != aRefs.end(); aRefsIt++) { - std::list::iterator aRefTo = aRefsIt->second.begin(); - for(; aRefTo != aRefsIt->second.end(); aRefTo++) { - if (*aRefTo) { - std::map >::iterator aFound = allRefs.find(*aRefTo); - if (aFound == allRefs.end()) { - allRefs[*aRefTo] = std::set(); - aFound = allRefs.find(*aRefTo); - } - aFound->second.insert(aFeature->data()->attribute(aRefsIt->first)); - } - } - } - } + collectReferences(aFeature->data(), allRefs); + } + NCollection_DataMap::Iterator aFolders(myFolders); + for(; aFolders.More(); aFolders.Next()) { + ObjectPtr aFolder = aFolders.Value(); + collectReferences(aFolder->data(), allRefs); } // second iteration: just compare back-references with existing in features and results for(aFeatures.Initialize(myFeatures); aFeatures.More(); aFeatures.Next()) { @@ -1328,7 +1338,7 @@ std::shared_ptr Model_Objects::findFolder( if (aFoundFolder) { AttributeReferencePtr aLastFeatAttr = aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID()); - if (aLastFeatAttr && aLastFeatAttr->isInitialized()) { + if (aLastFeatAttr) { // setup iterating inside a folder to find last feature ObjectPtr aLastFeature = aLastFeatAttr->value(); if (aLastFeature) { @@ -1390,6 +1400,13 @@ bool Model_Objects::moveToFolder( if (aFolderLabel.IsNull() || aLastFeatureLabel.IsNull()) return false; + AttributeReferencePtr aFirstFeatAttr = + theFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID()); + AttributeReferencePtr aLastFeatAttr = + theFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID()); + bool initFirstAttr = !aFirstFeatAttr->value().get(); + bool initLastAttr = !aLastFeatAttr->value().get(); + // check the folder is below the list of features bool isFolderBelow = false; TDF_Label aFeaturesLab = featuresLabel(); @@ -1424,22 +1441,119 @@ bool Model_Objects::moveToFolder( // move the folder in the list of references before the first feature RemoveFromRefArray(aFeaturesLab, aFolderLabel); AddToRefArray(aFeaturesLab, aFolderLabel, aPrevFeatureLabel); + // update first feature of the folder + initFirstAttr = true; } else { // update last feature of the folder - AttributeReferencePtr aLastFeatAttr = - theFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID()); - aLastFeatAttr->setValue(theFeatures.back()); + initLastAttr = true; } + if (initFirstAttr) + aFirstFeatAttr->setValue(theFeatures.front()); + if (initLastAttr) + aLastFeatAttr->setValue(theFeatures.back()); + updateHistory(ModelAPI_Feature::group()); 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) +{ + if (theFirstFeatureFolder.get()) { + if (theLastFeatureFolder.get()) + return theFirstFeatureFolder == theLastFeatureFolder ? theFirstFeatureFolder : FolderPtr(); + else + isExtractBefore = true; + return theFirstFeatureFolder; + } else if (theLastFeatureFolder.get()) { + isExtractBefore = false; + return theLastFeatureFolder; + } + // no folder found + return FolderPtr(); +} + bool Model_Objects::removeFromFolder( - const std::list >& theFeatures) + const std::list >& theFeatures, + const bool theBefore) { - /// \todo - return false; + if (theFeatures.empty()) + return false; + + FolderPtr aFirstFeatureFolder = inFolder(theFeatures.front(), ModelAPI_Folder::FIRST_FEATURE_ID()); + FolderPtr aLastFeatureFolder = inFolder(theFeatures.back(), ModelAPI_Folder::LAST_FEATURE_ID()); + + bool isExtractBeforeFolder = theBefore; + FolderPtr aFoundFolder = + isExtractionCorrect(aFirstFeatureFolder, aLastFeatureFolder, isExtractBeforeFolder); + if (!aFoundFolder) + return false; // list of features cannot be extracted + + // references of the current folder + ObjectPtr aFolderStartFeature; + ObjectPtr aFolderEndFeature; + if (aFirstFeatureFolder != aLastFeatureFolder) { + aFolderStartFeature = aFoundFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID())->value(); + aFolderEndFeature = aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID())->value(); + } + + FeaturePtr aFeatureToFind = isExtractBeforeFolder ? theFeatures.back() : theFeatures.front(); + std::shared_ptr aData = + std::static_pointer_cast(aFeatureToFind->data()); + if (!aData || !aData->isValid()) + return false; + TDF_Label aLabelToFind = aData->label().Father(); + + // search the label in the list of references + TDF_Label aFeaturesLab = featuresLabel(); + Handle(TDataStd_ReferenceArray) aRefs; + if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) + return false; // no reference array (something is wrong) + int aRefIndex = aRefs->Lower(); + for (; aRefIndex <= aRefs->Upper(); ++aRefIndex) + if (aRefs->Value(aRefIndex) == aLabelToFind) + break; + + // update folder position + if (isExtractBeforeFolder) { + aData = std::dynamic_pointer_cast(aFoundFolder->data()); + TDF_Label aFolderLabel = aData->label().Father(); + TDF_Label aPrevFeatureLabel = aRefs->Value(aRefIndex); + // update start reference of the folder + if (aFolderStartFeature.get()) + aFolderStartFeature = feature(aRefs->Value(aRefIndex + 1)); + // move the folder in the list of references after the last feature from the list + RemoveFromRefArray(aFeaturesLab, aFolderLabel); + AddToRefArray(aFeaturesLab, aFolderLabel, aPrevFeatureLabel); + } else { + // update end reference of the folder + if (aFolderEndFeature.get()) + aFolderEndFeature = feature(aRefs->Value(aRefIndex - 1)); + } + + // update folder references + aFoundFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID())->setValue(aFolderStartFeature); + aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID())->setValue(aFolderEndFeature); + + updateHistory(ModelAPI_Feature::group()); + return true; } diff --git a/src/Model/Model_Objects.h b/src/Model/Model_Objects.h index 5e1f0b350..19572e143 100644 --- a/src/Model/Model_Objects.h +++ b/src/Model/Model_Objects.h @@ -168,8 +168,13 @@ class Model_Objects bool moveToFolder(const std::list >& theFeatures, const std::shared_ptr& theFolder); //! Remove features from the folder + //! \param theFeatures list of features to be removed + //! \param theBefore extract features before the folder (this parameter is applicable only + //! when all features in the folder are taking out, + //! in other cases the direction is taken automatically) //! \return \c true if the features have been moved out - bool removeFromFolder(const std::list >& theFeatures); + bool removeFromFolder(const std::list >& theFeatures, + const bool theBefore = true); //! Sets the owner of this manager void setOwner(DocumentPtr theDoc); diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index 7ad725416..525805b1d 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -202,9 +202,14 @@ public: virtual bool moveToFolder(const std::list >& theFeatures, const std::shared_ptr& theFolder) = 0; //! Remove features from the folder + //! \param theFeatures list of features to be removed + //! \param theBefore extract features before the folder (this parameter is applicable only + //! when all features in the folder are taking out, + //! in other cases the direction is taken automatically) //! \return \c true if the features have been moved out virtual bool removeFromFolder( - const std::list >& theFeatures) = 0; + const std::list >& theFeatures, + const bool theBefore = true) = 0; //! Informs the document that it becomes active and some actions must be performed virtual void setActive(const bool theFlag) = 0; diff --git a/src/ModelAPI/ModelAPI_Folder.cpp b/src/ModelAPI/ModelAPI_Folder.cpp index 1cc97cb36..965529374 100644 --- a/src/ModelAPI/ModelAPI_Folder.cpp +++ b/src/ModelAPI/ModelAPI_Folder.cpp @@ -38,6 +38,9 @@ void ModelAPI_Folder::initAttributes() { data()->addAttribute(FIRST_FEATURE_ID(), ModelAPI_AttributeReference::typeId()); data()->addAttribute(LAST_FEATURE_ID(), ModelAPI_AttributeReference::typeId()); + // nullify references for sure + reference(FIRST_FEATURE_ID())->setValue(ObjectPtr()); + reference(LAST_FEATURE_ID())->setValue(ObjectPtr()); } void ModelAPI_Folder::execute() diff --git a/src/ModelAPI/Test/TestFolder_Update.py b/src/ModelAPI/Test/TestFolder_Update.py index 1ef1a8c6a..a118cbacf 100644 --- a/src/ModelAPI/Test/TestFolder_Update.py +++ b/src/ModelAPI/Test/TestFolder_Update.py @@ -109,7 +109,7 @@ toFolder.append(aPoint2) # move point to the folder aSession.startOperation() -aFolder = aPartDoc.findFolderAbove(toFolder) +aFolder = aPartDoc.findFolderBelow(toFolder) assert(aFolder is not None) isAdded = aPartDoc.moveToFolder(toFolder, aFolder) aSession.finishOperation() @@ -138,7 +138,7 @@ assert(aPartDoc.index(aPoint4, True) == 3), "Wrong index of the point: {}".forma # add a folder aSession.startOperation() -aFolder2 = aPartDoc.addFolder(aPoint3) +aFolder3 = aPartDoc.addFolder(aPoint3) aSession.finishOperation() NB_FEATURES_FULL += 1 @@ -149,10 +149,10 @@ assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT) # index without respect to foldering -assert(aPartDoc.index(aFolder2) == 4), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder2)) +assert(aPartDoc.index(aFolder3) == 4), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3)) assert(aPartDoc.index(aPoint4) == 6), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4)) # index according to folders -assert(aPartDoc.index(aFolder2, True) == 2), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder2, True)) +assert(aPartDoc.index(aFolder3, True) == 2), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True)) assert(aPartDoc.index(aPoint4, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True)) toFolder = FeatureList() @@ -173,14 +173,163 @@ assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT) # index without respect to foldering -assert(aPartDoc.index(aFolder2) == 4), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder2)) +assert(aPartDoc.index(aFolder3) == 4), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3)) assert(aPartDoc.index(aPoint3) == 5), "Wrong index of the point: {}".format(aPartDoc.index(aPoint3)) assert(aPartDoc.index(aPoint4) == 6), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4)) # index according to folders -assert(aPartDoc.index(aFolder2, True) == 2), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder2, True)) +assert(aPartDoc.index(aFolder3, True) == 2), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True)) assert(aPartDoc.index(aPoint3, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint3, True)) assert(aPartDoc.index(aPoint4, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True)) +# add more points to the folder to move them out +aPoint5 = newPoint(aPartDoc, 0., 0., 10.) +aPoint6 = newPoint(aPartDoc, 10., 0., 10.) +aPoint7 = newPoint(aPartDoc, 10., 10., 10.) +aPoint8 = newPoint(aPartDoc, 0., 10., 10.) + +toFolder = FeatureList() +toFolder.append(aPoint5) +toFolder.append(aPoint6) +toFolder.append(aPoint7) +toFolder.append(aPoint8) + +# move point to the folder +aSession.startOperation() +aFolder = aPartDoc.findFolderAbove(toFolder) +assert(aFolder is not None) +isAdded = aPartDoc.moveToFolder(toFolder, aFolder) +aSession.finishOperation() +assert(isAdded) + +NB_FEATURES_FULL += 4 +assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL) +assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT) + +assert(aPartDoc.index(aPoint5, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint5, True)) +assert(aPartDoc.index(aPoint6, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint6, True)) +assert(aPartDoc.index(aPoint7, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint7, True)) +assert(aPartDoc.index(aPoint8, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True)) + +assert(aFolder3.reference("first_feature").value() is not None) +assert(aFolder3.reference("last_feature").value() is not None) + +#========================================================================= +# Test 4. Remove a point from a folder before it +#========================================================================= +fromFolder = FeatureList() +fromFolder.append(aPoint3) + +aSession.startOperation() +isMovedOut = aPartDoc.removeFromFolder(fromFolder) +aSession.finishOperation() +assert(isMovedOut) + +NB_FEATURES_OUT += 1 +assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL) +assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT) + +assert(aPartDoc.index(aPoint3, True) == 2), "Wrong index of the point: {}".format(aPartDoc.index(aPoint3, True)) +assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True)) + +assert(aFolder3.reference("first_feature").value() is not None) +assert(aFolder3.reference("last_feature").value() is not None) + +#========================================================================= +# Test 5. Remove a point from a folder after it +#========================================================================= +fromFolder = FeatureList() +fromFolder.append(aPoint8) + +aSession.startOperation() +isMovedOut = aPartDoc.removeFromFolder(fromFolder) +aSession.finishOperation() +assert(isMovedOut) + +NB_FEATURES_OUT += 1 +assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL) +assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT) + +assert(aPartDoc.index(aPoint8, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True)) +assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True)) + +assert(aFolder3.reference("first_feature").value() is not None) +assert(aFolder3.reference("last_feature").value() is not None) + +#========================================================================= +# Test 6. Try to remove several points which are not start nor end in a folder +#========================================================================= +fromFolder = FeatureList() +fromFolder.append(aPoint5) +fromFolder.append(aPoint6) + +aSession.startOperation() +isMovedOut = aPartDoc.removeFromFolder(fromFolder) +aSession.finishOperation() +assert(isMovedOut is False) + +assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL) +assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT) + +assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True)) +assert(aPartDoc.index(aPoint5, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint5, True)) +assert(aPartDoc.index(aPoint6, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint6, True)) +assert(aPartDoc.index(aPoint8, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True)) + +assert(aFolder3.reference("first_feature").value() is not None) +assert(aFolder3.reference("last_feature").value() is not None) + +#========================================================================= +# Test 7. Remove several points from a folder after it +#========================================================================= +fromFolder = FeatureList() +fromFolder.append(aPoint6) +fromFolder.append(aPoint7) + +aSession.startOperation() +isMovedOut = aPartDoc.removeFromFolder(fromFolder) +aSession.finishOperation() +assert(isMovedOut) + +NB_FEATURES_OUT += 2 +assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL) +assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT) + +assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True)) +assert(aPartDoc.index(aPoint6, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint6, True)) +assert(aPartDoc.index(aPoint7, True) == 5), "Wrong index of the point: {}".format(aPartDoc.index(aPoint7, True)) +assert(aPartDoc.index(aPoint8, True) == 6), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True)) + +assert(aFolder3.reference("first_feature").value() is not None) +assert(aFolder3.reference("last_feature").value() is not None) + +#========================================================================= +# Test 8. Remove all remaining points from a folder after it +#========================================================================= +fromFolder = FeatureList() +fromFolder.append(aPoint4) +fromFolder.append(aPoint5) + +aSession.startOperation() +isMovedOut = aPartDoc.removeFromFolder(fromFolder, False) +aSession.finishOperation() +assert(isMovedOut) + +NB_FEATURES_OUT += 2 +assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL) +assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT) + +assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True)) +assert(aPartDoc.index(aPoint4, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True)) +assert(aPartDoc.index(aPoint5, True) == 5), "Wrong index of the point: {}".format(aPartDoc.index(aPoint5, True)) +assert(aPartDoc.index(aPoint6, True) == 6), "Wrong index of the point: {}".format(aPartDoc.index(aPoint6, True)) +assert(aPartDoc.index(aPoint7, True) == 7), "Wrong index of the point: {}".format(aPartDoc.index(aPoint7, True)) +assert(aPartDoc.index(aPoint8, True) == 8), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True)) + +# folder is empty +assert(aFolder3.reference("first_feature").value() is None) +assert(aFolder3.reference("last_feature").value() is None) + + from salome.shaper import model assert(model.checkPythonDump())