]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Task 2.3. Ability to put consecutive Features in a folder
authorazv <azv@opencascade.com>
Wed, 22 Nov 2017 07:59:14 +0000 (10:59 +0300)
committerazv <azv@opencascade.com>
Wed, 22 Nov 2017 13:25:54 +0000 (16:25 +0300)
Implementation of the necessary features

17 files changed:
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_Objects.cpp
src/Model/Model_Objects.h
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI.i
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Folder.cpp [new file with mode: 0644]
src/ModelAPI/ModelAPI_Folder.h [new file with mode: 0644]
src/ModelAPI/ModelAPI_swig.h
src/ModelAPI/Test/TestFolder_Create.py [new file with mode: 0644]
src/ModelHighAPI/CMakeLists.txt
src/ModelHighAPI/ModelHighAPI.i
src/ModelHighAPI/ModelHighAPI_Folder.cpp [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_Folder.h [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_swig.h
src/PythonAPI/model/services/__init__.py

index bb82a340e7190215deda3d9b8459ad96cb9236de..e8e9a588752204858e1880dde91e7180780f11b7 100755 (executable)
@@ -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> 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<ModelAPI_Object> Model_Document::objectByName(
@@ -1047,11 +1049,11 @@ const int Model_Document::index(std::shared_ptr<ModelAPI_Object> 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<ModelAPI_Feature> Model_Document::currentFeature(const bool theVisible)
@@ -1255,6 +1257,16 @@ std::shared_ptr<ModelAPI_ResultParameter> Model_Document::createParameter(
   return myObjs->createParameter(theFeatureData, theIndex);
 }
 
+std::shared_ptr<ModelAPI_Folder> Model_Document::addFolder(
+    std::shared_ptr<ModelAPI_Feature> theAddBefore)
+{
+  return myObjs->createFolder(theAddBefore);
+}
+
+void Model_Document::removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder)
+{
+}
+
 std::shared_ptr<ModelAPI_Feature> Model_Document::feature(
     const std::shared_ptr<ModelAPI_Result>& theResult)
 {
@@ -1489,6 +1501,11 @@ std::list<std::shared_ptr<ModelAPI_Feature> > Model_Document::allFeatures()
   return myObjs->allFeatures();
 }
 
+std::list<std::shared_ptr<ModelAPI_Object> > Model_Document::allObjects()
+{
+  return myObjs->allObjects();
+}
+
 void Model_Document::setActive(const bool theFlag)
 {
   if (theFlag != myIsActive) {
index 4b33be6af7044e11e3edd715c35eb1dfc82f692f..c16238c8927658305f07417de530e0c6b1b19544 100644 (file)
@@ -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<ModelAPI_Feature>
     feature(const std::shared_ptr<ModelAPI_Result>& theResult);
 
+  //! Creates a folder (group of the features in the object browser)
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Folder> addFolder(
+      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);
+
   ///! 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<std::shared_ptr<ModelAPI_Feature> > 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<std::shared_ptr<ModelAPI_Object> > allObjects();
+
   /// Returns the global identifier of the current transaction (needed for the update algo)
   MODEL_EXPORT virtual int transactionID();
   /// Increases the transaction ID
index 85460450ce703b410da807ee6836e5cd974a2f19..6010d6e5e5977bd18b5dee18ab82afa14d0367e1 100644 (file)
@@ -32,6 +32,7 @@
 #include <Model_ResultParameter.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_CompositeFeature.h>
+#include <ModelAPI_Folder.h>
 #include <ModelAPI_Tools.h>
 
 #include <Events_Loop.h>
 #include <TDF_LabelMap.hxx>
 #include <TDF_ListIteratorOfLabelList.hxx>
 
+static const std::string& groupNameFoldering(const std::string& theGroupID,
+                                             const bool theAllowFolder)
+{
+  if (theAllowFolder) {
+    static std::map<std::string, std::string> aNames;
+    std::map<std::string, std::string>::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<TDF_Label, ObjectPtr>::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<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(theGroupID);
   if (aHIter == myHistory.end()) {
-    std::vector<ObjectPtr> aResult = std::vector<ObjectPtr>();
+    std::vector<ObjectPtr> aResult;
+    std::vector<ObjectPtr> 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<ModelAPI_Object> Model_Objects::objectByName(
@@ -552,10 +615,11 @@ const int Model_Objects::index(std::shared_ptr<ModelAPI_Object> 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<ResultPtr>& theResults)
@@ -1111,6 +1175,48 @@ std::shared_ptr<ModelAPI_ResultParameter> Model_Objects::createParameter(
   return aResult;
 }
 
+std::shared_ptr<ModelAPI_Folder> Model_Objects::createFolder(
+    const std::shared_ptr<ModelAPI_Feature>& 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<Model_Data> aPrevData =
+        std::dynamic_pointer_cast<Model_Data>(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<ModelAPI_Feature> Model_Objects::feature(
     const std::shared_ptr<ModelAPI_Result>& 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<Model_Data> aData = std::static_pointer_cast<Model_Data>(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<std::shared_ptr<ModelAPI_Object> > Model_Objects::allObjects()
+{
+  std::list<std::shared_ptr<ModelAPI_Object> > 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<std::shared_ptr<ModelAPI_Feature> > Model_Objects::allFeatures()
 {
   std::list<std::shared_ptr<ModelAPI_Feature> > aResult;
index 57e02fa3492b539851d737261a4cd394acdf4270..15b8ed61888ca79a297e8f66bf34dadaf2d833c4 100644 (file)
@@ -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<ModelAPI_Feature>
     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);
+
   //! 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<std::shared_ptr<ModelAPI_Feature> > 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<std::shared_ptr<ModelAPI_Object> > allObjects();
+
   //! synchronises back references for the given object basing on the collected data
   void synchronizeBackRefsForObject(
     const std::set<std::shared_ptr<ModelAPI_Attribute>>& 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<TDF_Label, FeaturePtr> myFeatures;
 
+  /// Managed folders
+  NCollection_DataMap<TDF_Label, ObjectPtr> 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<std::string, std::vector<ObjectPtr> > myHistory;
index 092bb88a0aef868751259bae3889e33090ee3c72..dc2038c446b47275a58ef64c12246c7146750d6a 100644 (file)
@@ -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
 )
index 7c0466cdb0152f1ac71ea99f8dd0f5af10bec3b4..8a42a919d5a70963d53bf451bd3b334f7475a5e8 100644 (file)
@@ -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)
 %include "ModelAPI_ResultParameter.h"
 %include "ModelAPI_Tools.h"
 %include "ModelAPI_ResultCompSolid.h"
+#include "ModelAPI_Folder.h"
 
 // std::list -> []
 %template(StringList) std::list<std::string>;
@@ -167,6 +170,7 @@ template<class T1, class T2> std::shared_ptr<T1> shared_ptr_cast(std::shared_ptr
 %template(featureToCompositeFeature) shared_ptr_cast<ModelAPI_CompositeFeature, ModelAPI_Feature>;
 %template(objectToFeature) shared_ptr_cast<ModelAPI_Feature, ModelAPI_Object>;
 %template(objectToResult) shared_ptr_cast<ModelAPI_Result, ModelAPI_Object>;
+%template(objectToFolder) shared_ptr_cast<ModelAPI_Folder, ModelAPI_Object>;
 %template(compositeFeatureToFeature) shared_ptr_cast<ModelAPI_Feature, ModelAPI_CompositeFeature>;
 
 %template(modelAPI_Result) shared_ptr_cast<ModelAPI_Result, ModelAPI_Object>;
index 24d7c4c4bde7c58e1c4120108947845c2fe3f194..069bb4bfd29286c710e8384776d112b81692daab 100644 (file)
@@ -31,6 +31,7 @@
 #include <set>
 
 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<ModelAPI_Object> 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<ModelAPI_Object> 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<std::shared_ptr<ModelAPI_Feature> > 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<std::shared_ptr<ModelAPI_Object> > allObjects() = 0;
+
+  //! Creates a folder (group of the features in the object browser)
+  virtual std::shared_ptr<ModelAPI_Folder> addFolder(
+      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;
+
   //! 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 (file)
index 0000000..1cc97cb
--- /dev/null
@@ -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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "ModelAPI_Folder.h"
+
+#include <ModelAPI_AttributeReference.h>
+
+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 (file)
index 0000000..702931f
--- /dev/null
@@ -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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef ModelAPI_Folder_H_
+#define ModelAPI_Folder_H_
+
+#include <ModelAPI.h>
+#include <ModelAPI_Object.h>
+
+/**\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<ModelAPI_Folder> FolderPtr;
+
+#endif
index 470b8e3d46370fb71390c05a79a13674b1dcca3f..e9d740ce076c8dedb9bd0c6e5a909c048cd52d8f 100644 (file)
@@ -60,6 +60,7 @@
   #include "ModelAPI_ResultField.h"
   #include "ModelAPI_Tools.h"
   #include "ModelAPI_ResultCompSolid.h"
+  #include "ModelAPI_Folder.h"
 
   #include <memory>
   #include <string>
diff --git a/src/ModelAPI/Test/TestFolder_Create.py b/src/ModelAPI/Test/TestFolder_Create.py
new file mode 100644 (file)
index 0000000..6041aa5
--- /dev/null
@@ -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<mailto: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())
index f33878dcfc911ac0280a69afbd78c9b747784af4..9c0cfb10c7dabc5f3fe155efa7986b9f92d606f8 100644 (file)
@@ -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
index 7010d848143a09e50c63e061a6426e09b2fa5984..268c97635a651ce3d6bc44bf858f3d3d9d1c131d 100644 (file)
 %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 (file)
index 0000000..7cfa321
--- /dev/null
@@ -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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "ModelHighAPI_Folder.h"
+#include <ModelHighAPI_Selection.h>
+
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Folder.h>
+
+//--------------------------------------------------------------------------------------
+
+ModelHighAPI_Folder::ModelHighAPI_Folder(const std::shared_ptr<ModelAPI_Folder> & theFolder)
+{
+}
+
+
+ModelHighAPI_Folder::~ModelHighAPI_Folder()
+{
+}
+
+//--------------------------------------------------------------------------------------
+
+std::shared_ptr<ModelHighAPI_Folder> addFolder(const std::shared_ptr<ModelAPI_Document>& thePart)
+{
+  std::shared_ptr<ModelAPI_Folder> aFolder;//// = thePart->addFolder();
+  return std::shared_ptr<ModelHighAPI_Folder>(new ModelHighAPI_Folder(aFolder));
+}
diff --git a/src/ModelHighAPI/ModelHighAPI_Folder.h b/src/ModelHighAPI/ModelHighAPI_Folder.h
new file mode 100644 (file)
index 0000000..2c7bc45
--- /dev/null
@@ -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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef SRC_MODELHIGHAPI_MODELHIGHAPI_FOLDER_H_
+#define SRC_MODELHIGHAPI_MODELHIGHAPI_FOLDER_H_
+
+//--------------------------------------------------------------------------------------
+#include <ModelHighAPI_Interface.h>
+
+#include <memory>
+//--------------------------------------------------------------------------------------
+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<ModelAPI_Folder> & theFolder);
+  /// Destructor
+  MODELHIGHAPI_EXPORT virtual ~ModelHighAPI_Folder();
+};
+
+//--------------------------------------------------------------------------------------
+/**\ingroup CPPHighAPI
+ * \brief Create Folder feature
+ */
+MODELHIGHAPI_EXPORT
+std::shared_ptr<ModelHighAPI_Folder> addFolder(const std::shared_ptr<ModelAPI_Document>& theDoc);
+//--------------------------------------------------------------------------------------
+#endif /* SRC_MODELHIGHAPI_MODELHIGHAPI_FOLDER_H_ */
index 4a0bf71da8fb2f312f8107b8bcea6aeb054911fb..fb7b26c8fda35d6e85f860929692cdbf2cd54cf9 100644 (file)
@@ -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"
index 8c15e89ecaf19521c50982e8cf42c9c133bbacd0..db5279d84ec6c7995b930b2522c2602f434b5636 100644 (file)
@@ -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