From 7ab55ab9035e1f5c3249ec8d76993bb6aff006df Mon Sep 17 00:00:00 2001 From: azv Date: Wed, 22 Nov 2017 10:59:14 +0300 Subject: [PATCH] Task 2.3. Ability to put consecutive Features in a folder Implementation of the necessary features --- src/Model/Model_Document.cpp | 27 +++- src/Model/Model_Document.h | 19 ++- src/Model/Model_Objects.cpp | 170 ++++++++++++++++++++--- src/Model/Model_Objects.h | 28 +++- src/ModelAPI/CMakeLists.txt | 3 + src/ModelAPI/ModelAPI.i | 4 + src/ModelAPI/ModelAPI_Document.h | 19 ++- src/ModelAPI/ModelAPI_Folder.cpp | 45 ++++++ src/ModelAPI/ModelAPI_Folder.h | 107 ++++++++++++++ src/ModelAPI/ModelAPI_swig.h | 1 + src/ModelAPI/Test/TestFolder_Create.py | 100 +++++++++++++ src/ModelHighAPI/CMakeLists.txt | 2 + src/ModelHighAPI/ModelHighAPI.i | 1 + src/ModelHighAPI/ModelHighAPI_Folder.cpp | 44 ++++++ src/ModelHighAPI/ModelHighAPI_Folder.h | 54 +++++++ src/ModelHighAPI/ModelHighAPI_swig.h | 1 + src/PythonAPI/model/services/__init__.py | 1 + 17 files changed, 595 insertions(+), 31 deletions(-) create mode 100644 src/ModelAPI/ModelAPI_Folder.cpp create mode 100644 src/ModelAPI/ModelAPI_Folder.h create mode 100644 src/ModelAPI/Test/TestFolder_Create.py create mode 100644 src/ModelHighAPI/ModelHighAPI_Folder.cpp create mode 100644 src/ModelHighAPI/ModelHighAPI_Folder.h diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index bb82a340e..e8e9a5887 100755 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -925,7 +925,7 @@ FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurre int aSubs = aComp->numberOfSubs(false); for(int a = 0; a < aSubs; a++) { FeaturePtr aSub = aComp->subFeature(a, false); - if (myObjs->isLater(aSub, aCurrent)) { + if (aSub && myObjs->isLater(aSub, aCurrent)) { isModified = true; aCurrent = aSub; } @@ -1031,9 +1031,11 @@ std::shared_ptr Model_Document::subDoc(int theDocID) Model_Application::getApplication()->document(theDocID)); } -ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex) +ObjectPtr Model_Document::object(const std::string& theGroupID, + const int theIndex, + const bool theAllowFolder) { - return myObjs->object(theGroupID, theIndex); + return myObjs->object(theGroupID, theIndex, theAllowFolder); } std::shared_ptr Model_Document::objectByName( @@ -1047,11 +1049,11 @@ const int Model_Document::index(std::shared_ptr theObject) return myObjs->index(theObject); } -int Model_Document::size(const std::string& theGroupID) +int Model_Document::size(const std::string& theGroupID, const bool theAllowFolder) { if (myObjs == 0) // may be on close return 0; - return myObjs->size(theGroupID); + return myObjs->size(theGroupID, theAllowFolder); } std::shared_ptr Model_Document::currentFeature(const bool theVisible) @@ -1255,6 +1257,16 @@ std::shared_ptr Model_Document::createParameter( return myObjs->createParameter(theFeatureData, theIndex); } +std::shared_ptr Model_Document::addFolder( + std::shared_ptr theAddBefore) +{ + return myObjs->createFolder(theAddBefore); +} + +void Model_Document::removeFolder(std::shared_ptr theFolder) +{ +} + std::shared_ptr Model_Document::feature( const std::shared_ptr& theResult) { @@ -1489,6 +1501,11 @@ std::list > Model_Document::allFeatures() return myObjs->allFeatures(); } +std::list > Model_Document::allObjects() +{ + return myObjs->allObjects(); +} + void Model_Document::setActive(const bool theFlag) { if (theFlag != myIsActive) { diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 4b33be6af..c16238c89 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -137,10 +137,15 @@ class Model_Document : public ModelAPI_Document //! Returns the feature in the group by the index (started from zero) //! \param theGroupID group that contains a feature //! \param theIndex zero-based index of feature in the group - MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex); + //! \param theAllowFolder take into account grouping feature by folders + MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, + const int theIndex, + const bool theAllowFolder = false); //! Returns the number of features in the group - MODEL_EXPORT virtual int size(const std::string& theGroupID); + //! \param theGroupID group of objects + //! \param theAllowFolder take into account grouping feature by folders + MODEL_EXPORT virtual int size(const std::string& theGroupID, const bool theAllowFolder = false); //! Returns the feature that is currently edited in this document, normally //! this is the latest created feature @@ -199,6 +204,12 @@ class Model_Document : public ModelAPI_Document MODEL_EXPORT virtual std::shared_ptr feature(const std::shared_ptr& theResult); + //! Creates a folder (group of the features in the object browser) + MODEL_EXPORT virtual std::shared_ptr addFolder( + std::shared_ptr theAddBefore = std::shared_ptr()); + //! Removes the folder from the document (all features in the folder will be kept). + MODEL_EXPORT virtual void removeFolder(std::shared_ptr theFolder); + ///! 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 bool& executeFeatures() {return myExecuteFeatures;} @@ -221,6 +232,10 @@ class Model_Document : public ModelAPI_Document ///! history. Not very fast method, for calling once, not in big cycles. MODEL_EXPORT virtual std::list > allFeatures(); + //! Returns all objects of the document including the hidden features which are not in + //! history. Not very fast method, for calling once, not in big cycles. + MODEL_EXPORT virtual std::list > allObjects(); + /// Returns the global identifier of the current transaction (needed for the update algo) MODEL_EXPORT virtual int transactionID(); /// Increases the transaction ID diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 85460450c..6010d6e5e 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,22 @@ #include #include +static const std::string& groupNameFoldering(const std::string& theGroupID, + const bool theAllowFolder) +{ + if (theAllowFolder) { + static std::map aNames; + std::map::const_iterator aFound = aNames.find(theGroupID); + if (aFound == aNames.end()) { + aNames[theGroupID] = std::string("__") + theGroupID; + aFound = aNames.find(theGroupID); + } + return aFound->second; + } + return theGroupID; +} + + static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, results) // feature sub-labels @@ -92,6 +109,15 @@ Model_Objects::~Model_Objects() aFeature->erase(); myFeatures.UnBind(aFeaturesIter.Key()); } + while (!myFolders.IsEmpty()) { + NCollection_DataMap::Iterator aFoldersIter(myFolders); + ObjectPtr aFolder = aFoldersIter.Value(); + static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Folder::group()); + ModelAPI_EventCreator::get()->sendUpdated(aFolder, EVENT_DISP); + aFolder->erase(); + myFolders.UnBind(aFoldersIter.Key()); + } myHistory.clear(); aLoop->activateFlushes(isActive); // erase update, because features are destroyed and update should not performed for them anywhere @@ -387,7 +413,9 @@ void Model_Objects::createHistory(const std::string& theGroupID) { std::map >::iterator aHIter = myHistory.find(theGroupID); if (aHIter == myHistory.end()) { - std::vector aResult = std::vector(); + std::vector aResult; + std::vector aResultOutOfFolder; + FeaturePtr aLastFeatureInFolder; // iterate the array of references and get feature by feature from the array bool isFeature = theGroupID == ModelAPI_Feature::group(); Handle(TDataStd_ReferenceArray) aRefs; @@ -401,6 +429,9 @@ void Model_Objects::createHistory(const std::string& theGroupID) if (isFeature) { // here may be also disabled features if (!isSub && aFeature->isInHistory()) { aResult.push_back(aFeature); + // the feature is out of the folders + if (aLastFeatureInFolder.get() == NULL) + aResultOutOfFolder.push_back(aFeature); } } else if (!aFeature->isDisabled()) { // iterate all results of not-disabled feature // construction results of sub-features should not be in the tree @@ -418,12 +449,34 @@ void Model_Objects::createHistory(const std::string& theGroupID) } } } + + // the feature closes the folder, so the next features will be treated as out-of-folder + if (aLastFeatureInFolder.get() && aLastFeatureInFolder == aFeature) + aLastFeatureInFolder = FeaturePtr(); + + } else { + // it may be a folder + ObjectPtr aFolder = folder(aRefs->Value(a)); + if (aFolder.get()) { + aResult.push_back(aFolder); + + // get the last feature in the folder + AttributeReferencePtr aLastFeatAttr = + aFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID()); + if (aLastFeatAttr) + aLastFeatureInFolder = ModelAPI_Feature::feature(aLastFeatAttr->value()); + } } } } // to be sure that isConcealed did not update the history (issue 1089) during the iteration - if (myHistory.find(theGroupID) == myHistory.end()) + if (myHistory.find(theGroupID) == myHistory.end()) { myHistory[theGroupID] = aResult; + + // store the features placed out of any folder + const std::string& anOutOfFolderGroupID = groupNameFoldering(theGroupID, true); + myHistory[anOutOfFolderGroupID] = aResultOutOfFolder; + } } } @@ -439,6 +492,13 @@ void Model_Objects::updateHistory(const std::string theGroup) myHistory.erase(aHIter); // erase from map => this means that it is not synchronized } +ObjectPtr Model_Objects::folder(TDF_Label theLabel) const +{ + if (myFolders.IsBound(theLabel)) + return myFolders.Find(theLabel); + return ObjectPtr(); +} + FeaturePtr Model_Objects::feature(TDF_Label theLabel) const { if (myFeatures.IsBound(theLabel)) @@ -489,12 +549,15 @@ ObjectPtr Model_Objects::object(TDF_Label theLabel) return FeaturePtr(); // not found } -ObjectPtr Model_Objects::object(const std::string& theGroupID, const int theIndex) +ObjectPtr Model_Objects::object(const std::string& theGroupID, + const int theIndex, + const bool theAllowFolder) { if (theIndex == -1) return ObjectPtr(); - createHistory(theGroupID); - return myHistory[theGroupID][theIndex]; + const std::string& aGroupID = groupNameFoldering(theGroupID, theAllowFolder); + createHistory(aGroupID); + return myHistory[aGroupID][theIndex]; } std::shared_ptr Model_Objects::objectByName( @@ -552,10 +615,11 @@ const int Model_Objects::index(std::shared_ptr theObject) return -1; } -int Model_Objects::size(const std::string& theGroupID) +int Model_Objects::size(const std::string& theGroupID, const bool theAllowFolder) { - createHistory(theGroupID); - return int(myHistory[theGroupID].size()); + const std::string& aGroupID = groupNameFoldering(theGroupID, theAllowFolder); + createHistory(aGroupID); + return int(myHistory[aGroupID].size()); } void Model_Objects::allResults(const std::string& theGroupID, std::list& theResults) @@ -1111,6 +1175,48 @@ std::shared_ptr Model_Objects::createParameter( return aResult; } +std::shared_ptr Model_Objects::createFolder( + const std::shared_ptr& theBeforeThis) +{ + FolderPtr aFolder(new ModelAPI_Folder); + if (!aFolder) + return aFolder; + + TDF_Label aFeaturesLab = featuresLabel(); + TDF_Label aFolderLab = aFeaturesLab.NewChild(); + // store feature in the features array: before "initData" because in macro features + // in initData it creates new features, appeared later than this + TDF_Label aPrevFeatureLab; + if (theBeforeThis.get()) { // searching for the previous feature label + std::shared_ptr aPrevData = + std::dynamic_pointer_cast(theBeforeThis->data()); + if (aPrevData.get()) { + aPrevFeatureLab = nextLabel(aPrevData->label().Father(), true); + } + } else { // find the label of the last feature + Handle(TDataStd_ReferenceArray) aRefs; + if (aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) + aPrevFeatureLab = aRefs->Value(aRefs->Upper()); + } + AddToRefArray(aFeaturesLab, aFolderLab, aPrevFeatureLab); + + // keep the feature ID to restore document later correctly + TDataStd_Comment::Set(aFolderLab, aFolder->getKind().c_str()); + myFolders.Bind(aFolderLab, aFolder); + // must be before the event sending: for OB the feature is already added + updateHistory(ModelAPI_Folder::group()); + + // must be after binding to the map because of "Box" macro feature that + // creates other features in "initData" + initData(aFolder, aFolderLab, TAG_FEATURE_ARGUMENTS); + // event: folder is added, must 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); + ModelAPI_EventCreator::get()->sendUpdated(aFolder, anEvent); + + return aFolder; +} + std::shared_ptr Model_Objects::feature( const std::shared_ptr& theResult) { @@ -1247,23 +1353,31 @@ ResultPtr Model_Objects::findByName(const std::string theName) return aResult; } +TDF_Label Model_Objects::nextLabel(TDF_Label theCurrent, const bool theReverse) +{ + Handle(TDataStd_ReferenceArray) aRefs; + if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { + for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { // iterate all existing features + TDF_Label aCurLab = aRefs->Value(a); + if (aCurLab.IsEqual(theCurrent)) { + a += theReverse ? -1 : 1; + if (a >= aRefs->Lower() && a <= aRefs->Upper()) + return aRefs->Value(a); + break; // finish iiteration: it's last feature + } + } + } + return TDF_Label(); +} + FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theReverse) { std::shared_ptr aData = std::static_pointer_cast(theCurrent->data()); if (aData.get() && aData->isValid()) { TDF_Label aFeatureLabel = aData->label().Father(); - Handle(TDataStd_ReferenceArray) aRefs; - if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { - for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { // iterate all existing features - TDF_Label aCurLab = aRefs->Value(a); - if (aCurLab.IsEqual(aFeatureLabel)) { - a += theReverse ? -1 : 1; - if (a >= aRefs->Lower() && a <= aRefs->Upper()) - return feature(aRefs->Value(a)); - break; // finish iiteration: it's last feature - } - } - } + TDF_Label aNextLabel = nextLabel(aFeatureLabel, theReverse); + if (!aNextLabel.IsNull()) + return feature(aNextLabel); } return FeaturePtr(); // not found, last, or something is wrong } @@ -1311,6 +1425,22 @@ bool Model_Objects::isLater(FeaturePtr theLater, FeaturePtr theCurrent) const return false; // not found, or something is wrong } +std::list > Model_Objects::allObjects() +{ + std::list > aResult; + Handle(TDataStd_ReferenceArray) aRefs; + if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { + for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { + ObjectPtr anObject = object(aRefs->Value(a)); + if (!anObject.get()) // is it a folder? + anObject = folder(aRefs->Value(a)); + if (anObject.get()) + aResult.push_back(anObject); + } + } + return aResult; +} + std::list > Model_Objects::allFeatures() { std::list > aResult; diff --git a/src/Model/Model_Objects.h b/src/Model/Model_Objects.h index 57e02fa34..15b8ed618 100644 --- a/src/Model/Model_Objects.h +++ b/src/Model/Model_Objects.h @@ -96,10 +96,15 @@ class Model_Objects //! Returns the feature in the group by the index (started from zero) //! \param theGroupID group that contains a feature //! \param theIndex zero-based index of feature in the group - ObjectPtr object(const std::string& theGroupID, const int theIndex); + //! \param theAllowFolder take into account grouping feature by folders + ObjectPtr object(const std::string& theGroupID, + const int theIndex, + const bool theAllowFolder = false); //! Returns the number of features in the group - int size(const std::string& theGroupID); + //! \param theGroupID group of objects + //! \param theAllowFolder take into account grouping feature by folders + int size(const std::string& theGroupID, const bool theAllowFolder = false); //! Returns all (and disabled) results of the given type. //! Not fast method (iterates all features). @@ -141,6 +146,10 @@ class Model_Objects std::shared_ptr feature(const std::shared_ptr& theResult); + /// Creates a folder (group of the features in the object browser) + std::shared_ptr createFolder( + const std::shared_ptr& theBeforeThis); + //! Sets the owner of this manager void setOwner(DocumentPtr theDoc); @@ -214,6 +223,11 @@ class Model_Objects /// Returns true if theLater is in history of features creation later than theCurrent bool isLater(FeaturePtr theLater, FeaturePtr theCurrent) const; + /// Returns the next or previous label + /// \param theCurrent given label + /// \param theReverse if it is true, iterates in reverced order (next becomes previous) + TDF_Label nextLabel(TDF_Label theCurrent, const bool theReverse = false); + /// Returns the result group identifier of the given feature (for this at least one result must /// be created before) std::string featureResultGroup(FeaturePtr theFeature); @@ -222,6 +236,10 @@ class Model_Objects //! history. Not very fast method, for calling once, not in big cycles. std::list > allFeatures(); + //! Returns all objects of the document including the hidden features which are not in + //! history. Not very fast method, for calling once, not in big cycles. + std::list > allObjects(); + //! synchronises back references for the given object basing on the collected data void synchronizeBackRefsForObject( const std::set>& theNewRefs, ObjectPtr theObject); @@ -236,6 +254,9 @@ class Model_Objects int theResultIndex, std::string& theParentName) const; + /// Return object representing a folder or empty pointer + ObjectPtr folder(TDF_Label theLabel) const; + private: TDF_Label myMain; ///< main label of the data storage @@ -245,6 +266,9 @@ class Model_Objects /// For optimization mapped by labels NCollection_DataMap myFeatures; + /// Managed folders + NCollection_DataMap myFolders; + /// Map from group id to the array that contains all objects located in history. /// Each array is updated by demand from scratch, by browing all the features in the history. std::map > myHistory; diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index 092bb88a0..dc2038c44 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -51,6 +51,7 @@ SET(PROJECT_HEADERS ModelAPI_Expression.h ModelAPI_Feature.h ModelAPI_FeatureValidator.h + ModelAPI_Folder.h ModelAPI_IReentrant.h ModelAPI_Object.h ModelAPI_Plugin.h @@ -94,6 +95,7 @@ SET(PROJECT_SOURCES ModelAPI_Expression.cpp ModelAPI_Feature.cpp ModelAPI_FeatureValidator.cpp + ModelAPI_Folder.cpp ModelAPI_IReentrant.cpp ModelAPI_Object.cpp ModelAPI_Plugin.cpp @@ -187,4 +189,5 @@ ADD_UNIT_TESTS(TestConstants.py TestCustomName_Rename.py TestCustomName_RotateGroup.py TestCustomName_Translation.py + TestFolder_Create.py ) diff --git a/src/ModelAPI/ModelAPI.i b/src/ModelAPI/ModelAPI.i index 7c0466cdb..8a42a919d 100644 --- a/src/ModelAPI/ModelAPI.i +++ b/src/ModelAPI/ModelAPI.i @@ -51,6 +51,7 @@ %feature("director") ModelAPI_Feature; %feature("director") ModelAPI_CompositeFeature; %feature("director") ModelAPI_Data; +%feature("director") ModelAPI_Folder; // shared pointers // For ModelAPI_ResultConstruction.shape() @@ -62,6 +63,7 @@ %shared_ptr(ModelAPI_Feature) %shared_ptr(ModelAPI_CompositeFeature) %shared_ptr(ModelAPI_Data) +%shared_ptr(ModelAPI_Folder) %shared_ptr(ModelAPI_Attribute) %shared_ptr(ModelAPI_AttributeDocRef) %shared_ptr(ModelAPI_AttributeDouble) @@ -151,6 +153,7 @@ %include "ModelAPI_ResultParameter.h" %include "ModelAPI_Tools.h" %include "ModelAPI_ResultCompSolid.h" +#include "ModelAPI_Folder.h" // std::list -> [] %template(StringList) std::list; @@ -167,6 +170,7 @@ template std::shared_ptr shared_ptr_cast(std::shared_ptr %template(featureToCompositeFeature) shared_ptr_cast; %template(objectToFeature) shared_ptr_cast; %template(objectToResult) shared_ptr_cast; +%template(objectToFolder) shared_ptr_cast; %template(compositeFeatureToFeature) shared_ptr_cast; %template(modelAPI_Result) shared_ptr_cast; diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index 24d7c4c4b..069bb4bfd 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -31,6 +31,7 @@ #include class ModelAPI_Feature; +class ModelAPI_Folder; class ModelAPI_Object; class ModelAPI_Result; class ModelAPI_ResultConstruction; @@ -89,8 +90,10 @@ public: //! Returns the object in the group by the index (started from zero) //! \param theGroupID group that contains an object //! \param theIndex zero-based index of feature in the group + //! \param theAllowFolder take into account grouping feature by folders virtual std::shared_ptr object(const std::string& theGroupID, - const int theIndex) = 0; + const int theIndex, + const bool theAllowFolder = false) = 0; //! Returns the first found object in the group by the object name //! \param theGroupID group that contains an object @@ -105,7 +108,9 @@ public: virtual const int index(std::shared_ptr theObject) = 0; //! Returns the number of objects in the group of objects - virtual int size(const std::string& theGroupID) = 0; + //! \param theGroupID group of objects + //! \param theAllowFolder take into account grouping feature by folders + virtual int size(const std::string& theGroupID, const bool theAllowFolder = false) = 0; //! Returns the feature that is currently edited in this document, normally //! this is the latest created feature @@ -170,6 +175,16 @@ public: //! history. Not very fast method, for calling once, not in big cycles. virtual std::list > allFeatures() = 0; + //! Returns all objects of the document including the hidden features which are not in + //! history. Not very fast method, for calling once, not in big cycles. + virtual std::list > allObjects() = 0; + + //! Creates a folder (group of the features in the object browser) + virtual std::shared_ptr addFolder( + std::shared_ptr theAddBefore) = 0; + //! Removes the folder from the document (all features in the folder will be kept). + virtual void removeFolder(std::shared_ptr theFolder) = 0; + //! Informs the document that it becomes active and some actions must be performed virtual void setActive(const bool theFlag) = 0; //! Returns true if this document is currently active diff --git a/src/ModelAPI/ModelAPI_Folder.cpp b/src/ModelAPI/ModelAPI_Folder.cpp new file mode 100644 index 000000000..1cc97cb36 --- /dev/null +++ b/src/ModelAPI/ModelAPI_Folder.cpp @@ -0,0 +1,45 @@ +// 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 +// + +#include "ModelAPI_Folder.h" + +#include + +ModelAPI_Folder::ModelAPI_Folder() +{ +} + +ModelAPI_Folder::~ModelAPI_Folder() +{ +} + +void ModelAPI_Folder::init() +{ +} + +void ModelAPI_Folder::initAttributes() +{ + data()->addAttribute(FIRST_FEATURE_ID(), ModelAPI_AttributeReference::typeId()); + data()->addAttribute(LAST_FEATURE_ID(), ModelAPI_AttributeReference::typeId()); +} + +void ModelAPI_Folder::execute() +{ +} diff --git a/src/ModelAPI/ModelAPI_Folder.h b/src/ModelAPI/ModelAPI_Folder.h new file mode 100644 index 000000000..702931ffe --- /dev/null +++ b/src/ModelAPI/ModelAPI_Folder.h @@ -0,0 +1,107 @@ +// 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 +// + +#ifndef ModelAPI_Folder_H_ +#define ModelAPI_Folder_H_ + +#include +#include + +/**\class ModelAPI_Folder + * \ingroup DataModel + * \brief Folder feature (groups the features). + */ +class ModelAPI_Folder : public ModelAPI_Object +{ +public: + MODELAPI_EXPORT ModelAPI_Folder(); + /// To virtually destroy the fields of successors + MODELAPI_EXPORT virtual ~ModelAPI_Folder(); + + /// Folder feature ID + static const std::string& ID() + { + static const std::string MY_FOLDER_ID("Folder"); + return MY_FOLDER_ID; + } + + /// Returns the unique kind of a feature + virtual const std::string& getKind() + { + static const std::string& MY_KIND = ModelAPI_Folder::ID(); + return MY_KIND; + } + + /// Returns the group identifier of all features + inline static std::string group() + { + static std::string MY_GROUP = "Folders"; + return MY_GROUP; + } + + /// Returns the group identifier of this result + virtual std::string groupName() + { + return group(); + } + + /// Attribute referring first feature in the folder + static const std::string& FIRST_FEATURE_ID() + { + static const std::string MY_FIRST_FEATURE_ID("first_feature"); + return MY_FIRST_FEATURE_ID; + } + + /// Attribute referring last feature in the folder + static const std::string& LAST_FEATURE_ID() + { + static const std::string MY_LAST_FEATURE_ID("last_feature"); + return MY_LAST_FEATURE_ID; + } + + /// Request for initialization of data model of the object: adding all attributes + MODELAPI_EXPORT virtual void initAttributes(); + + /// Computes or recomputes the results + MODELAPI_EXPORT virtual void execute(); + + /// Returns the feature is disabled or not. + virtual bool isDisabled() + { return false; } + + // + // Helper methods, aliases for data()->method() + // ----------------------------------------------------------------------------------------------- + /// Returns the name stored in the attribute + inline std::string name() + { + return data()->name(); + } + +protected: + /// This method is called just after creation of the object: it must initialize + /// all fields, normally initialized in the constructor + MODELAPI_EXPORT virtual void init(); +}; + +//! Pointer on a folder object +typedef std::shared_ptr FolderPtr; + +#endif diff --git a/src/ModelAPI/ModelAPI_swig.h b/src/ModelAPI/ModelAPI_swig.h index 470b8e3d4..e9d740ce0 100644 --- a/src/ModelAPI/ModelAPI_swig.h +++ b/src/ModelAPI/ModelAPI_swig.h @@ -60,6 +60,7 @@ #include "ModelAPI_ResultField.h" #include "ModelAPI_Tools.h" #include "ModelAPI_ResultCompSolid.h" + #include "ModelAPI_Folder.h" #include #include diff --git a/src/ModelAPI/Test/TestFolder_Create.py b/src/ModelAPI/Test/TestFolder_Create.py new file mode 100644 index 000000000..6041aa505 --- /dev/null +++ b/src/ModelAPI/Test/TestFolder_Create.py @@ -0,0 +1,100 @@ +## 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 +## + +#========================================================================= +# Initialization of the test +#========================================================================= +from ModelAPI import * + +__updated__ = "2017-11-22" + +#========================================================================= +# Test 1. Check the Folder is created in PartSet +#========================================================================= +aSession = ModelAPI_Session.get() +aPartSetDoc = aSession.activeDocument() + +aSession.startOperation() +aPoint0 = aPartSetDoc.addFeature("Point") +aPoint0Data = aPoint0.data() +assert(aPoint0Data is not None) +aPoint0Data.real("x").setValue(0.) +aPoint0Data.real("y").setValue(0.) +aPoint0Data.real("z").setValue(0.) +aPoint0Data.string("creation_method").setValue("by_xyz") +aSession.finishOperation() + +aSession.startOperation() +aPoint1 = aPartSetDoc.addFeature("Point") +aPoint1Data = aPoint1.data() +assert(aPoint1Data is not None) +aPoint1Data.real("x").setValue(0.) +aPoint1Data.real("y").setValue(0.) +aPoint1Data.real("z").setValue(0.) +aPoint1Data.string("creation_method").setValue("by_xyz") +aSession.finishOperation() + +# Folder before the feature +aSession.startOperation() +aFolder1 = aPartSetDoc.addFolder(aPoint1) +aSession.finishOperation() + +assert(aPartSetDoc.size("Folders") == 1) +assert(aFolder1.name() == "Folder_1") + +## Folder at the end of features list +#aSession.startOperation() +#aPartSetDoc.addFolder() +#aSession.finishOperation() +#assert(aPartSetDoc.size("Folders") == 2) + +#========================================================================= +# Test 2. Check the Folder is created in a Part +#========================================================================= +aSession.startOperation() +aPart = aSession.moduleDocument().addFeature("Part") +aSession.finishOperation() + +# check part is a last feature +aFeaturesList = aSession.moduleDocument().allObjects() +aLast = aFeaturesList[len(aFeaturesList)-1] +assert(aLast.data().isEqual(aPart.data())), "Part is not a last object in the list" + +# add point and a folder before it +aPartDoc = aSession.activeDocument() +aSession.startOperation() +aPoint2 = aPartDoc.addFeature("Point") +aPoint2Data = aPoint2.data() +assert(aPoint2Data is not None) +aPoint2Data.real("x").setValue(0.) +aPoint2Data.real("y").setValue(0.) +aPoint2Data.real("z").setValue(0.) +aPoint2Data.string("creation_method").setValue("by_xyz") +aSession.finishOperation() + +aSession.startOperation() +aFolder2 = aPartDoc.addFolder(aPoint2) +aSession.finishOperation() + +assert(aPartDoc.size("Folders") == 1) +assert(aFolder2.data().name() == "Folder_1") + +from salome.shaper import model +assert(model.checkPythonDump()) diff --git a/src/ModelHighAPI/CMakeLists.txt b/src/ModelHighAPI/CMakeLists.txt index f33878dcf..9c0cfb10c 100644 --- a/src/ModelHighAPI/CMakeLists.txt +++ b/src/ModelHighAPI/CMakeLists.txt @@ -33,6 +33,7 @@ SET(PROJECT_HEADERS ModelHighAPI_Services.h ModelHighAPI_Tools.h ModelHighAPI_FeatureStore.h + ModelHighAPI_Folder.h ) SET(PROJECT_SOURCES @@ -46,6 +47,7 @@ SET(PROJECT_SOURCES ModelHighAPI_Services.cpp ModelHighAPI_Tools.cpp ModelHighAPI_FeatureStore.cpp + ModelHighAPI_Folder.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/ModelHighAPI/ModelHighAPI.i b/src/ModelHighAPI/ModelHighAPI.i index 7010d8481..268c97635 100644 --- a/src/ModelHighAPI/ModelHighAPI.i +++ b/src/ModelHighAPI/ModelHighAPI.i @@ -348,6 +348,7 @@ %include "ModelHighAPI_Dumper.h" %include "ModelHighAPI_Integer.h" %include "ModelHighAPI_Interface.h" +%include "ModelHighAPI_Folder.h" %include "ModelHighAPI_RefAttr.h" %include "ModelHighAPI_Reference.h" %include "ModelHighAPI_Selection.h" diff --git a/src/ModelHighAPI/ModelHighAPI_Folder.cpp b/src/ModelHighAPI/ModelHighAPI_Folder.cpp new file mode 100644 index 000000000..7cfa3215b --- /dev/null +++ b/src/ModelHighAPI/ModelHighAPI_Folder.cpp @@ -0,0 +1,44 @@ +// 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 +// + +#include "ModelHighAPI_Folder.h" +#include + +#include +#include + +//-------------------------------------------------------------------------------------- + +ModelHighAPI_Folder::ModelHighAPI_Folder(const std::shared_ptr & theFolder) +{ +} + + +ModelHighAPI_Folder::~ModelHighAPI_Folder() +{ +} + +//-------------------------------------------------------------------------------------- + +std::shared_ptr addFolder(const std::shared_ptr& thePart) +{ + std::shared_ptr aFolder;//// = thePart->addFolder(); + return std::shared_ptr(new ModelHighAPI_Folder(aFolder)); +} diff --git a/src/ModelHighAPI/ModelHighAPI_Folder.h b/src/ModelHighAPI/ModelHighAPI_Folder.h new file mode 100644 index 000000000..2c7bc45d9 --- /dev/null +++ b/src/ModelHighAPI/ModelHighAPI_Folder.h @@ -0,0 +1,54 @@ +// 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 +// + +#ifndef SRC_MODELHIGHAPI_MODELHIGHAPI_FOLDER_H_ +#define SRC_MODELHIGHAPI_MODELHIGHAPI_FOLDER_H_ + +//-------------------------------------------------------------------------------------- +#include + +#include +//-------------------------------------------------------------------------------------- +class ModelAPI_Document; +class ModelAPI_Folder; +class ModelHighAPI_Selection; +//-------------------------------------------------------------------------------------- +/**\class ModelHighAPI_Folder + * \ingroup CPPHighAPI + * \brief Class for filling ModelAPI_Folder + */ +class ModelHighAPI_Folder +{ +public: + /// Constructor for a folder + MODELHIGHAPI_EXPORT + explicit ModelHighAPI_Folder(const std::shared_ptr & theFolder); + /// Destructor + MODELHIGHAPI_EXPORT virtual ~ModelHighAPI_Folder(); +}; + +//-------------------------------------------------------------------------------------- +/**\ingroup CPPHighAPI + * \brief Create Folder feature + */ +MODELHIGHAPI_EXPORT +std::shared_ptr addFolder(const std::shared_ptr& theDoc); +//-------------------------------------------------------------------------------------- +#endif /* SRC_MODELHIGHAPI_MODELHIGHAPI_FOLDER_H_ */ diff --git a/src/ModelHighAPI/ModelHighAPI_swig.h b/src/ModelHighAPI/ModelHighAPI_swig.h index 4a0bf71da..fb7b26c8f 100644 --- a/src/ModelHighAPI/ModelHighAPI_swig.h +++ b/src/ModelHighAPI/ModelHighAPI_swig.h @@ -28,6 +28,7 @@ #include "ModelHighAPI.h" #include "ModelHighAPI_Double.h" #include "ModelHighAPI_Dumper.h" + #include "ModelHighAPI_Folder.h" #include "ModelHighAPI_Integer.h" #include "ModelHighAPI_Interface.h" #include "ModelHighAPI_Macro.h" diff --git a/src/PythonAPI/model/services/__init__.py b/src/PythonAPI/model/services/__init__.py index 8c15e89ec..db5279d84 100644 --- a/src/PythonAPI/model/services/__init__.py +++ b/src/PythonAPI/model/services/__init__.py @@ -8,5 +8,6 @@ from ModelHighAPI import apply as do from ModelHighAPI import updateFeatures from ModelHighAPI import undo, redo from ModelHighAPI import reset +from ModelHighAPI import addFolder from ModelHighAPI import ModelHighAPI_Selection as selection from ModelHighAPI import checkPythonDump as checkPythonDump -- 2.39.2