void Model_Document::removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder)
{
+ if (theFolder)
+ myObjs->removeFolder(theFolder);
+}
+
+std::shared_ptr<ModelAPI_Folder> Model_Document::findFolderAbove(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures)
+{
+ return myObjs->findFolder(theFeatures, false);
+}
+
+std::shared_ptr<ModelAPI_Folder> Model_Document::findFolderBelow(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures)
+{
+ return myObjs->findFolder(theFeatures, true);
+}
+
+bool Model_Document::moveToFolder(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+ const std::shared_ptr<ModelAPI_Folder>& theFolder)
+{
+ return myObjs->moveToFolder(theFeatures, theFolder);
+}
+
+bool Model_Document::removeFromFolder(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures)
+{
+ return myObjs->removeFromFolder(theFeatures);
}
std::shared_ptr<ModelAPI_Feature> Model_Document::feature(
std::shared_ptr<ModelAPI_Feature> theAddBefore = std::shared_ptr<ModelAPI_Feature>());
//! Removes the folder from the document (all features in the folder will be kept).
MODEL_EXPORT virtual void removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder);
+ //! Search a folder above the list of features applicable to store them
+ //! (it means the list of features stored in the folder should be consequential)
+ //! \return Empty pointer if there is no applicable folder
+ MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Folder> findFolderAbove(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures);
+ //! Search a folder below the list of features applicable to store them
+ //! (it means the list of features stored in the folder should be consequential)
+ //! \return Empty pointer if there is no applicable folder
+ MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Folder> findFolderBelow(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures);
+ //! Add a list of features to the folder. The correctness of the adding is not performed
+ //! (such checks have been done in corresponding find.. method).
+ //! \return \c true if the movement is successfull
+ MODEL_EXPORT virtual bool moveToFolder(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+ const std::shared_ptr<ModelAPI_Folder>& theFolder);
+ //! Remove features from the folder
+ //! \return \c true if the features have been moved out
+ MODEL_EXPORT virtual bool removeFromFolder(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures);
///! 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
return aFolder;
}
+void Model_Objects::removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder)
+{
+ /// \todo
+}
+
+static FeaturePtr limitingFeature(std::list<FeaturePtr>& theFeatures, const bool isLast)
+{
+ FeaturePtr aFeature;
+ if (isLast) {
+ aFeature = theFeatures.back();
+ theFeatures.pop_back();
+ } else {
+ aFeature = theFeatures.front();
+ theFeatures.pop_front();
+ }
+ return aFeature;
+}
+
+std::shared_ptr<ModelAPI_Folder> Model_Objects::findFolder(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+ const bool theBelow)
+{
+ if (theFeatures.empty())
+ return FolderPtr(); // nothing to move
+
+ TDF_Label aFeaturesLab = featuresLabel();
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+ return FolderPtr(); // no reference array (something is wrong)
+
+ std::list<std::shared_ptr<ModelAPI_Feature> > aFeatures = theFeatures;
+ std::shared_ptr<ModelAPI_Feature> aLimitingFeature = limitingFeature(aFeatures, theBelow);
+
+ std::shared_ptr<Model_Data> aData =
+ std::static_pointer_cast<Model_Data>(aLimitingFeature->data());
+ if (!aData || !aData->isValid())
+ return FolderPtr(); // invalid feature
+
+ // label of the first feature in the list for fast searching
+ TDF_Label aFirstFeatureLabel = aData->label().Father();
+
+ // find a folder above the features and
+ // check the given features represent a sequential list of objects following the folder
+ FolderPtr aFoundFolder;
+ TDF_Label aLastFeatureInFolder;
+ int aRefIndex = aRefs->Lower();
+ for(; aRefIndex <= aRefs->Upper(); ++aRefIndex) { // iterate all existing features
+ TDF_Label aCurLabel = aRefs->Value(aRefIndex);
+ if (IsEqual(aCurLabel, aFirstFeatureLabel))
+ break; // no need to continue searching
+
+ // searching the folder below, just continue to search last feature from the list
+ if (theBelow)
+ continue;
+
+ if (!aLastFeatureInFolder.IsNull()) {
+ if (IsEqual(aCurLabel, aLastFeatureInFolder))
+ aLastFeatureInFolder.Nullify(); // the last feature in the folder is achived
+ continue;
+ }
+
+ aFoundFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(folder(aCurLabel));
+ if (aFoundFolder) {
+ AttributeReferencePtr aLastFeatAttr =
+ aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+ if (aLastFeatAttr && aLastFeatAttr->isInitialized()) {
+ // setup iterating inside a folder to find last feature
+ ObjectPtr aLastFeature = aLastFeatAttr->value();
+ if (aLastFeature) {
+ aData = std::static_pointer_cast<Model_Data>(aLastFeature->data());
+ if (aData && aData->isValid())
+ aLastFeatureInFolder = aData->label().Father();
+ }
+ }
+ }
+ }
+
+ if (theBelow && aRefIndex < aRefs->Upper()) {
+ // check the next object is a folder
+ TDF_Label aLabel = aRefs->Value(aRefIndex + 1);
+ aFoundFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(folder(aLabel));
+ }
+
+ if (!aLastFeatureInFolder.IsNull() || // the last feature of the folder above is not found
+ !aFoundFolder)
+ return FolderPtr();
+
+ // check the given features are sequential list
+ int aStep = theBelow ? -1 : 1;
+ for (aRefIndex += aStep;
+ !aFeatures.empty() && aRefIndex >= aRefs->Lower() && aRefIndex <= aRefs->Upper();
+ aRefIndex += aStep) {
+ TDF_Label aCurLabel = aRefs->Value(aRefIndex);
+ TDF_Label aFeatureLabel;
+
+ aLimitingFeature = limitingFeature(aFeatures, theBelow);
+ aData = std::static_pointer_cast<Model_Data>(aLimitingFeature->data());
+ if (aData && aData->isValid())
+ aFeatureLabel = aData->label().Father();
+
+ if (!IsEqual(aCurLabel, aFeatureLabel))
+ return FolderPtr(); // not a sequential list
+ }
+
+ return aFoundFolder;
+}
+
+bool Model_Objects::moveToFolder(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+ const std::shared_ptr<ModelAPI_Folder>& theFolder)
+{
+ if (theFeatures.empty() || !theFolder)
+ return false;
+
+ // labels for the folder and last feature in the list
+ TDF_Label aFolderLabel, aLastFeatureLabel;
+ std::shared_ptr<Model_Data> aData =
+ std::static_pointer_cast<Model_Data>(theFolder->data());
+ if (aData && aData->isValid())
+ aFolderLabel = aData->label().Father();
+ aData = std::static_pointer_cast<Model_Data>(theFeatures.back()->data());
+ if (aData && aData->isValid())
+ aLastFeatureLabel = aData->label().Father();
+
+ if (aFolderLabel.IsNull() || aLastFeatureLabel.IsNull())
+ return false;
+
+ // check the folder is below the list of features
+ bool isFolderBelow = false;
+ TDF_Label aFeaturesLab = featuresLabel();
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+ return false; // no reference array (something is wrong)
+ for (int aRefIndex = aRefs->Lower(); aRefIndex <= aRefs->Upper(); ++aRefIndex) {
+ TDF_Label aCurLabel = aRefs->Value(aRefIndex);
+ if (aCurLabel == aFolderLabel)
+ break; // folder is above the features
+ else if (aCurLabel == aLastFeatureLabel) {
+ isFolderBelow = true;
+ break;
+ }
+ }
+
+ if (isFolderBelow) {
+ aData = std::static_pointer_cast<Model_Data>(theFeatures.front()->data());
+ if (!aData || !aData->isValid())
+ return false;
+ TDF_Label aPrevFeatureLabel = aData->label().Father();
+ // label of the feature before the first feature in the list
+ for (int aRefIndex = aRefs->Lower(); aRefIndex <= aRefs->Upper(); ++aRefIndex)
+ if (aPrevFeatureLabel == aRefs->Value(aRefIndex)) {
+ if (aRefIndex == aRefs->Lower())
+ aPrevFeatureLabel.Nullify();
+ else
+ aPrevFeatureLabel = aRefs->Value(aRefIndex - 1);
+ break;
+ }
+
+ // move the folder in the list of references before the first feature
+ RemoveFromRefArray(aFeaturesLab, aFolderLabel);
+ AddToRefArray(aFeaturesLab, aFolderLabel, aPrevFeatureLabel);
+ } else {
+ // update last feature of the folder
+ AttributeReferencePtr aLastFeatAttr =
+ theFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+ aLastFeatAttr->setValue(theFeatures.back());
+ }
+
+ updateHistory(ModelAPI_Feature::group());
+ return true;
+}
+
+bool Model_Objects::removeFromFolder(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures)
+{
+ /// \todo
+ return false;
+}
+
+
std::shared_ptr<ModelAPI_Feature> Model_Objects::feature(
const std::shared_ptr<ModelAPI_Result>& theResult)
{
/// Creates a folder (group of the features in the object browser)
std::shared_ptr<ModelAPI_Folder> createFolder(
const std::shared_ptr<ModelAPI_Feature>& theBeforeThis);
+ //! Removes the folder from the document (all features in the folder will be kept).
+ void removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder);
+ //! Search a folder applicable for the list of features
+ //! (it means the list of features stored in the folder should be consequential)
+ //! \param theFeatures list of features to be added to folder
+ //! \param theBelow search the folder below the features (if \c false, search above)
+ //! \return Empty pointer if there is no applicable folder
+ std::shared_ptr<ModelAPI_Folder> findFolder(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+ const bool theBelow);
+ //! Add a list of features to the folder. The correctness of the adding is not performed
+ //! (such checks have been done in corresponding find.. method).
+ //! \return \c true if the movement is successfull
+ bool moveToFolder(const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+ const std::shared_ptr<ModelAPI_Folder>& theFolder);
+ //! Remove features from the folder
+ //! \return \c true if the features have been moved out
+ bool removeFromFolder(const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures);
//! Sets the owner of this manager
void setOwner(DocumentPtr theDoc);
TestCustomName_RotateGroup.py
TestCustomName_Translation.py
TestFolder_Create.py
+ TestFolder_Update.py
)
std::shared_ptr<ModelAPI_Feature> theAddBefore) = 0;
//! Removes the folder from the document (all features in the folder will be kept).
virtual void removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder) = 0;
+ //! Search a folder above the list of features applicable to store them
+ //! (it means the list of features stored in the folder should be consequential)
+ //! \return Empty pointer if there is no applicable folder
+ virtual std::shared_ptr<ModelAPI_Folder> findFolderAbove(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures) = 0;
+ //! Search a folder below the list of features applicable to store them
+ //! (it means the list of features stored in the folder should be consequential)
+ //! \return Empty pointer if there is no applicable folder
+ virtual std::shared_ptr<ModelAPI_Folder> findFolderBelow(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures) = 0;
+ //! Add a list of features to the folder. The correctness of the adding is not performed
+ //! (such checks have been done in corresponding find.. method).
+ //! \return \c true if the movement is successfull
+ virtual bool moveToFolder(const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+ const std::shared_ptr<ModelAPI_Folder>& theFolder) = 0;
+ //! Remove features from the folder
+ //! \return \c true if the features have been moved out
+ virtual bool removeFromFolder(
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures) = 0;
//! Informs the document that it becomes active and some actions must be performed
virtual void setActive(const bool theFlag) = 0;
{
return data()->name();
}
+ /// Returns the reference attribute by the identifier
+ inline std::shared_ptr<ModelAPI_AttributeReference> reference(const std::string& theID)
+ {
+ return data()->reference(theID);
+ }
protected:
/// This method is called just after creation of the object: it must initialize
--- /dev/null
+## Copyright (C) 2014-2017 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
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## Lesser General Public License for more details.
+##
+## 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
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from ModelAPI import *
+
+__updated__ = "2017-11-23"
+
+aSession = ModelAPI_Session.get()
+
+
+def newPoint(theDocument, theX, theY, theZ):
+ aSession.startOperation()
+ aPoint = theDocument.addFeature("Point")
+ aPointData = aPoint.data()
+ assert(aPointData is not None)
+ aPointData.real("x").setValue(theX)
+ aPointData.real("y").setValue(theY)
+ aPointData.real("z").setValue(theZ)
+ aPointData.string("creation_method").setValue("by_xyz")
+ aSession.finishOperation()
+ return aPoint
+
+
+#=========================================================================
+# Test 1. Add a point into a folder above
+#=========================================================================
+aSession.startOperation()
+aPart = aSession.moduleDocument().addFeature("Part")
+aSession.finishOperation()
+
+# add point and a folder before it
+aPartDoc = aSession.activeDocument()
+aPoint1 = newPoint(aPartDoc, 0., 0., 0.)
+
+aSession.startOperation()
+aFolder1 = aPartDoc.addFolder(aPoint1)
+aSession.finishOperation()
+
+NB_FEATURES_FULL = 2
+NB_FEATURES_OUT = 2
+
+assert(aPartDoc.size("Folders") == 1), "Wrong number of folders: {}".format(aPartDoc.size("Folders"))
+assert(aPartDoc.size("Features") == 2), "Wrong number of features: {}".format(aPartDoc.size("Features"))
+FOLDER_NAME_EXPECTED = "Folder_1"
+assert(aFolder1.name() == FOLDER_NAME_EXPECTED), "Actual name '{}', expected '{}'".format(aFolder1.name(), FOLDER_NAME_EXPECTED)
+
+toFolder = FeatureList()
+toFolder.append(aPoint1)
+
+# 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_OUT -= 1
+# full number of features
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+# number of features outside the folder
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+#=========================================================================
+# Test 2. Add a point into a folder below
+#=========================================================================
+aPoint2 = newPoint(aPartDoc, 10., 0., 0.)
+aPoint3 = newPoint(aPartDoc, 10., 10., 0.)
+
+NB_FEATURES_FULL += 2
+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)
+
+# add a folder
+aSession.startOperation()
+aFolder2 = aPartDoc.addFolder(aPoint3)
+aSession.finishOperation()
+
+NB_FEATURES_FULL += 1
+NB_FEATURES_OUT += 1
+
+assert(aPartDoc.size("Folders") == 2), "Wrong number of folders: {}".format(aPartDoc.size("Folders"))
+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)
+
+toFolder = FeatureList()
+toFolder.append(aPoint2)
+
+# 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_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)
+
+#=========================================================================
+# Test 3. Add several points into a folder
+#=========================================================================
+aPoint4 = newPoint(aPartDoc, 0., 10., 0.)
+
+NB_FEATURES_FULL += 1
+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)
+
+# add a folder
+aSession.startOperation()
+aFolder2 = aPartDoc.addFolder(aPoint3)
+aSession.finishOperation()
+
+NB_FEATURES_FULL += 1
+NB_FEATURES_OUT += 1
+
+assert(aPartDoc.size("Folders") == 3), "Wrong number of folders: {}".format(aPartDoc.size("Folders"))
+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)
+
+toFolder = FeatureList()
+toFolder.append(aPoint3)
+toFolder.append(aPoint4)
+
+# 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_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)
+
+
+from salome.shaper import model
+assert(model.checkPythonDump())