Salome HOME
Merge branch 'Results_Hierarchy'
authormpv <mikhail.ponikarov@opencascade.com>
Thu, 16 Aug 2018 18:41:52 +0000 (21:41 +0300)
committermpv <mikhail.ponikarov@opencascade.com>
Thu, 16 Aug 2018 18:41:52 +0000 (21:41 +0300)
86 files changed:
src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp
src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp
src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp
src/FeaturesPlugin/FeaturesPlugin_FusionFaces.cpp
src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp
src/FeaturesPlugin/FeaturesPlugin_Union.cpp
src/FeaturesPlugin/FeaturesPlugin_ValidatorTransform.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/FeaturesPlugin/Test/Test1922.py
src/FeaturesPlugin/Test/TestBooleanCompSolids.py
src/FeaturesPlugin/Test/TestCompositeFeaturesOnCompSolids.py
src/FeaturesPlugin/Test/TestRemoveSubShapes.py
src/FeaturesPlugin/Test/TestUnion.py
src/GeomAPI/CMakeLists.txt
src/GeomValidators/GeomValidators_BodyShapes.cpp
src/GeomValidators/GeomValidators_IntersectionSelection.cpp [new file with mode: 0644]
src/GeomValidators/GeomValidators_ShapeType.cpp
src/Model/CMakeLists.txt
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/Model/Model_AttributeSelectionList.cpp
src/Model/Model_AttributeSelectionList.h
src/Model/Model_BodyBuilder.cpp
src/Model/Model_Data.cpp
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_Events.cpp
src/Model/Model_Events.h
src/Model/Model_Objects.cpp
src/Model/Model_Objects.h
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultBody.h
src/Model/Model_ResultCompSolid.cpp [deleted file]
src/Model/Model_ResultCompSolid.h [deleted file]
src/Model/Model_SelectionNaming.cpp
src/Model/Model_Session.cpp
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI.i
src/ModelAPI/ModelAPI_AttributeSelection.h
src/ModelAPI/ModelAPI_AttributeSelectionList.h
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Events.h
src/ModelAPI/ModelAPI_ResultBody.cpp
src/ModelAPI/ModelAPI_ResultBody.h
src/ModelAPI/ModelAPI_ResultCompSolid.cpp [deleted file]
src/ModelAPI/ModelAPI_ResultCompSolid.h [deleted file]
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModelAPI/ModelAPI_swig.h
src/ModelHighAPI/ModelHighAPI_Dumper.cpp
src/ModelHighAPI/ModelHighAPI_Selection.cpp
src/ModuleBase/ModuleBase_ITreeNode.h
src/ModuleBase/ModuleBase_IWorkshop.h
src/ModuleBase/ModuleBase_OperationFeature.cpp
src/ModuleBase/ModuleBase_ResultPrs.cpp
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
src/ModuleBase/ModuleBase_WidgetSelector.cpp
src/ModuleBase/ModuleBase_WidgetValidated.cpp
src/PartSet/CMakeLists.txt
src/PartSet/PartSet_DataModel.cpp
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_OperationPrs.cpp
src/PartSet/PartSet_ResultSketchPrs.cpp
src/PartSet/PartSet_TreeNodes.cpp
src/PartSet/PartSet_TreeNodes.h
src/PartSet/PartSet_Validators.cpp
src/PythonAPI/model/tests/tests.py
src/SketchSolver/SketchSolver_Manager.cpp
src/XGUI/XGUI_DataModel.cpp
src/XGUI/XGUI_DataModel.h
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_Displayer.h
src/XGUI/XGUI_ModuleConnector.cpp
src/XGUI/XGUI_ModuleConnector.h
src/XGUI/XGUI_ObjectsBrowser.cpp
src/XGUI/XGUI_ObjectsBrowser.h
src/XGUI/XGUI_Selection.cpp
src/XGUI/XGUI_SelectionMgr.cpp
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_WorkshopListener.cpp
test.API/SHAPER/Transformations/TestTranslation_3.py

index 9104486c1b0b337fe615068d27f25e6b1178f2e9..99afc6e8dbf6d78c1c37838d639f26fad7caf9f4 100644 (file)
@@ -24,7 +24,6 @@
 #include <ModelAPI_Document.h>
 #include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_AttributeInteger.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Session.h>
@@ -100,7 +99,7 @@ void FeaturesPlugin_Boolean::execute()
       return;
     }
     ResultPtr aContext = anObjectAttr->context();
-    ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+    ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
     if(aResCompSolidPtr.get()
         && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) {
       std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
index eebff3615f35824001011694ce5f3dac715756c8..c4c4914e5f4f7f56d311bf3b16cdb5797004b205 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "FeaturesPlugin_BooleanCut.h"
 
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Tools.h>
 
@@ -54,7 +54,7 @@ void FeaturesPlugin_BooleanCut::execute()
       return;
     }
     ResultPtr aContext = anObjectAttr->context();
-    ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+    ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
     if (aResCompSolidPtr.get())
     {
       std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
index 1d7d14a5f74ba86904db9f125e75061c5f05180d..0319ee264c5ac9eac9d8ebe5a9d194cc59b010c1 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "FeaturesPlugin_BooleanFuse.h"
 
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeBoolean.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
@@ -79,7 +79,7 @@ void FeaturesPlugin_BooleanFuse::execute()
       return;
     }
     ResultPtr aContext = anObjectAttr->context();
-    ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+    ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
     if (!isSimpleCreation
         && aResCompSolidPtr.get()
         && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) {
index ebc6549588eb11bc4ed6c4f7972e5a76f5cc1049..f0aa745dd3251110493eb09a0aa2b0fe9e202427 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "FeaturesPlugin_BooleanSmash.h"
 
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Tools.h>
 
@@ -60,7 +60,7 @@ void FeaturesPlugin_BooleanSmash::execute()
       return;
     }
     ResultPtr aContext = anObjectAttr->context();
-    ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+    ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
     if (aResCompSolidPtr.get())
     {
       std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
index f54449b36ed98d0e6939561bcfea1eebfab2ef8f..9cdf2b7ccd45eafe2de8dcb2a7a4975c838dc6a1 100644 (file)
@@ -21,7 +21,6 @@
 #include "FeaturesPlugin_CompositeBoolean.h"
 
 #include <ModelAPI_AttributeSelectionList.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_Tools.h>
 
 #include <GeomAlgoAPI_Boolean.h>
@@ -123,7 +122,7 @@ bool FeaturesPlugin_CompositeBoolean::makeBoolean(const ListOfShape& theTools,
       return false;
     }
     ResultPtr aContext = anObjectAttr->context();
-    ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+    ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
     if(aResCompSolidPtr.get()) {
       GeomShapePtr aContextShape = aResCompSolidPtr->shape();
       std::map<GeomShapePtr, ListOfShape>::iterator anIt = aCompSolidsObjects.begin();
index 30f922aa8be2b236e159f6a3eefbe698a2f7cfbb..eab8b03ca8c4721d6ae00316736b76c321fb6076 100644 (file)
@@ -25,7 +25,6 @@
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Validator.h>
@@ -113,7 +112,7 @@ void FeaturesPlugin_Fillet::execute()
       return;
 
     ResultPtr aContext = anObjectAttr->context();
-    ResultCompSolidPtr aCtxOwner = ModelAPI_Tools::compSolidOwner(aContext);
+    ResultBodyPtr aCtxOwner = ModelAPI_Tools::bodyOwner(aContext);
     GeomShapePtr aParent = aCtxOwner ? aCtxOwner->shape() : aContext->shape();
     if (!aParent)
       return;
index a57403e1af8b1cbd417f8fd6cb6e88edb6d9c6c8..b3cc312c52097f8113056fb743f35972132a157e 100644 (file)
@@ -23,7 +23,6 @@
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
index a63ac8af06c5bfabb3c44626d260b84cb2052eaf..75b1d9c09dceec344b4969a45518951d7d32f82e 100644 (file)
@@ -23,7 +23,6 @@
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
@@ -72,14 +71,14 @@ void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
   }
 
   ResultPtr aContext = aShapeAttrSelection->context();
-  ResultCompSolidPtr aResultCompSolid =
-    std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
-  if(!aResultCompSolid.get()) {
+  ResultBodyPtr aResultBody =
+    std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
+  if (!aResultBody.get()) {
     aSubShapesToKeepAttrList->clear();
     aSubShapesToRemoveAttrList->clear();
     return;
   }
-  const int aNumOfSubs = aResultCompSolid->numberOfSubs();
+  const int aNumOfSubs = aResultBody->numberOfSubs();
 
   GeomShapePtr aBaseShape = aShapeAttrSelection->value();
   if(!aBaseShape.get()) {
@@ -101,8 +100,8 @@ void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
       if(aNumOfSubs == 0) {
         aSubShapesToKeepAttrList->append(aContext, aSubShape);
       } else {
-        for(int anIndex = 0; anIndex < aResultCompSolid->numberOfSubs(); ++anIndex) {
-          ResultBodyPtr aSubResult = aResultCompSolid->subResult(anIndex);
+        for (int anIndex = 0; anIndex < aResultBody->numberOfSubs(); ++anIndex) {
+          ResultBodyPtr aSubResult = aResultBody->subResult(anIndex);
           if(aSubResult->shape()->isEqual(aSubShape)) {
             aSubShapesToKeepAttrList->append(aSubResult, aSubShape);
             break;
@@ -135,8 +134,8 @@ void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
         if(aNumOfSubs == 0) {
           aSubShapesToRemoveAttrList->append(aContext, aSubShape);
         } else {
-          for(int anIndex = 0; anIndex < aResultCompSolid->numberOfSubs(); ++anIndex) {
-            ResultBodyPtr aSubResult = aResultCompSolid->subResult(anIndex);
+          for (int anIndex = 0; anIndex < aResultBody->numberOfSubs(); ++anIndex) {
+            ResultBodyPtr aSubResult = aResultBody->subResult(anIndex);
             if(aSubResult->shape()->isEqual(aSubShape)) {
               aSubShapesToRemoveAttrList->append(aSubResult, aSubShape);
               break;
@@ -170,8 +169,8 @@ void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
         if(aNumOfSubs == 0) {
           aSubShapesToKeepAttrList->append(aContext, aSubShape);
         } else {
-          for(int anIndex = 0; anIndex < aResultCompSolid->numberOfSubs(); ++anIndex) {
-            ResultBodyPtr aSubResult = aResultCompSolid->subResult(anIndex);
+          for (int anIndex = 0; anIndex < aResultBody->numberOfSubs(); ++anIndex) {
+            ResultBodyPtr aSubResult = aResultBody->subResult(anIndex);
             if(aSubResult->shape()->isEqual(aSubShape)) {
               aSubShapesToKeepAttrList->append(aSubResult, aSubShape);
               break;
index 76683a26fa5a866c2e57a40affcf19d468a82cdd..33bd7450b473240a9628247f6af01064b41909b8 100644 (file)
@@ -29,7 +29,7 @@
 #include <GeomAPI_ShapeIterator.h>
 
 #include <ModelAPI_AttributeSelectionList.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_Tools.h>
 
 //=================================================================================================
@@ -59,7 +59,7 @@ void FeaturesPlugin_Union::execute()
       return;
     }
     ResultPtr aContext = anObjectAttr->context();
-    ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+    ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
     if(aResCompSolidPtr.get()) {
       std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
       std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
index 41dd47afb9751f5bb55b8d04786caf88f0460ebb..13a0292e0d0bdb60f2576c569ddb7b5b59cb0833 100755 (executable)
@@ -25,7 +25,6 @@
 #include "ModelAPI_AttributeSelectionList.h"
 #include "ModelAPI_ResultPart.h"
 #include "ModelAPI_ResultBody.h"
-#include "ModelAPI_ResultCompSolid.h"
 #include "ModelAPI_Session.h"
 
 bool FeaturesPlugin_ValidatorTransform::isValid(const AttributePtr& theAttribute,
@@ -59,7 +58,7 @@ bool FeaturesPlugin_ValidatorTransform::isValid(const AttributePtr& theAttribute
     else { // Part document: Result CompSolid is valid
       aValid = aResult->groupName() == ModelAPI_ResultBody::group();
       if (aValid) {
-        ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
+        ResultBodyPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
         aValid = aComp.get() != NULL;
       }
     }
index 13b2c6cafd33f2918029f8456b368bc1ce55a020..4ab4e48cc1b151bcff7fe87fe58f2b25c0355846 100644 (file)
@@ -34,7 +34,7 @@
 #include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_Feature.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Tools.h>
 
@@ -586,8 +586,11 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
     }
     ResultPtr aContext = anAttrSelection->context();
     if(!aContext.get()) {
-      theError = "Error: Empty selection context.";
-      return false;
+      FeaturePtr aContFeat = anAttrSelection->contextFeature();
+      if (!aContFeat.get()) {
+        theError = "Error: Empty selection context.";
+        return false;
+      }
     }
     ResultConstructionPtr aResultConstruction =
       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
@@ -599,15 +602,15 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
       }
     }
     std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
-    GeomShapePtr aContextShape = aContext->shape();
     if(!aShape.get()) {
+      GeomShapePtr aContextShape = aContext->shape();
       aShape = aContextShape;
     }
     if(!aShape.get()) {
       theError = "Error: Empty shape.";
       return false;
     }
-    if(!aShape->isEqual(aContextShape)) {
+    if (aContext.get() && !aShape->isEqual(aContext->shape())) {
       theError = "Error: Local selection not allowed.";
       return false;
     }
@@ -676,7 +679,7 @@ bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAtt
       return false;
     }
 
-    ResultCompSolidPtr aContextOwner = ModelAPI_Tools::compSolidOwner(aContext);
+    ResultBodyPtr aContextOwner = ModelAPI_Tools::bodyOwner(aContext);
     GeomShapePtr anOwner = aContextOwner.get() ? aContextOwner->shape() : aContext->shape();
 
     if (anOwner->shapeType() != GeomAPI_Shape::SOLID &&
@@ -729,11 +732,22 @@ bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& the
       return false;
     }
 
-    ResultCompSolidPtr aResultCompsolid =
-      std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
-    if(aResultCompsolid.get()) {
+    ResultBodyPtr aResultBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
+    if(aResultBody.get()) {
       continue;
     }
+    FeaturePtr aResultFeature = aSelectAttr->contextFeature();
+    if(aResultFeature.get()) {
+      bool aOkRes = false;
+      std::list<ResultPtr>::const_iterator aFRes = aResultFeature->results().cbegin();
+      for(; aFRes != aResultFeature->results().cend() && !aOkRes; aFRes++) {
+        ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aFRes);
+        if (aBody.get() && !aBody->isDisabled())
+          aOkRes = true;
+      }
+      if (aOkRes)
+        continue;
+    }
 
     theError = "Error: Only body shapes and construction planes are allowed for selection.";
     return false;
@@ -893,8 +907,8 @@ bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttr
       return false;
     }
 
-    ResultCompSolidPtr aResult =
-      std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
+    ResultBodyPtr aResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
     if(!aResult.get()) {
       continue;
     }
@@ -1041,7 +1055,7 @@ bool FeaturesPlugin_ValidatorBooleanArguments::isValid(
   std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
 
   bool isAllInSameCompSolid = true;
-  ResultCompSolidPtr aCompSolid;
+  ResultBodyPtr aCompSolid;
 
   AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
   if (anAttrSelList)
@@ -1051,7 +1065,7 @@ bool FeaturesPlugin_ValidatorBooleanArguments::isValid(
     {
       AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
       ResultPtr aContext = anAttr->context();
-      ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+      ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
       if (aResCompSolidPtr.get())
       {
         if (aCompSolid.get())
@@ -1083,7 +1097,7 @@ bool FeaturesPlugin_ValidatorBooleanArguments::isValid(
       {
         AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
         ResultPtr aContext = anAttr->context();
-        ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+        ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
         if (aResCompSolidPtr.get())
         {
           if (aCompSolid.get())
@@ -1198,7 +1212,7 @@ bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid(
 
     if (aShape->isSolid() || aShape->isCompSolid()) {
       aSelectedShapesType = GeomAPI_Shape::SOLID;
-      ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+      ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
       if (aResCompSolidPtr.get()) {
         GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
         aSelectedCompSolidsInOtherList.bind(aCompSolidShape, aCompSolidShape);
@@ -1264,7 +1278,7 @@ bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid(
         return false;
       }
 
-      ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+      ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
       if (aResCompSolidPtr.get()) {
         GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
         if (aSelectedCompSolidsInOtherList.isBound(aCompSolidShape)) {
@@ -1424,7 +1438,7 @@ bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
   std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
 
   bool isAllInSameCompSolid = true;
-  ResultCompSolidPtr aCompSolid;
+  ResultBodyPtr aCompSolid;
 
   AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
   if (anAttrSelList) {
@@ -1432,7 +1446,7 @@ bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
     for (int anIndex = 0; anIndex < anObjectsNb; ++anIndex) {
       AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
       ResultPtr aContext = anAttr->context();
-      ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+      ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
       if (aResCompSolidPtr.get()) {
         if (aCompSolid.get()) {
           isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
@@ -1456,7 +1470,7 @@ bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
         for (int anIndex = 0; anIndex < aToolsNb; ++anIndex) {
           AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
           ResultPtr aContext = anAttr->context();
-          ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
+          ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
           if (aResCompSolidPtr.get()) {
             if (aCompSolid.get()) {
               isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
index a9224658b368932c2b511a233b3e0ce5ab92831a..8b1fc660b7715b59a850e78602b78790d4e0671c 100644 (file)
@@ -165,7 +165,7 @@ Partition_1 = model.addPartition(Part_1_doc, [model.selection("EDGE", "Extrusion
 model.end()
 PartitionFeature = Partition_1.feature()
 assert(len(PartitionFeature.results()) == 1)
-PartitionResult = modelAPI_ResultCompSolid(modelAPI_ResultBody(PartitionFeature.firstResult()))
+PartitionResult = modelAPI_ResultBody(PartitionFeature.firstResult())
 assert(PartitionResult.numberOfSubs() == 22)
 
 assert(model.checkPythonDump())
index 23dfe5c972f538ebd349f20f4c97d0150a58b743..d529c4cc50812ad31f5b53f783e7321ef484cc84 100644 (file)
@@ -118,7 +118,7 @@ aSession.finishOperation()
 #=========================================================================
 aSession.startOperation()
 aBooleanFt = aPart.addFeature("Cut")
-aBooleanFt.selectionList("main_objects").append(modelAPI_ResultCompSolid(extrudedObjects[0]).subResult(1), None)
+aBooleanFt.selectionList("main_objects").append(extrudedObjects[0].subResult(1), None)
 aBooleanFt.selectionList("tool_objects").append(extrudedObjects[1], None)
 aBooleanFt.execute()
 aSession.finishOperation()
@@ -133,7 +133,6 @@ aSession.undo()
 #=========================================================================
 aSession.startOperation()
 aBooleanFt = aPart.addFeature("Fuse")
-aBooleanFt.string("creation_method").setValue("advanced")
 aBooleanFt.selectionList("main_objects").append(modelAPI_ResultCompSolid(extrudedObjects[0]).subResult(1), None)
 aBooleanFt.selectionList("tool_objects").append(extrudedObjects[1], None)
 aBooleanFt.boolean("remove_intersection_edges").setValue(False)
index c885ab2704766e044e78f6c72830bf8620ba7ec6..47caabb1d0e461c8a09d5a53afdb49a66462d149 100644 (file)
@@ -158,7 +158,7 @@ aFromResult = aFromPlaneFeature.firstResult()
 aFromShape = modelAPI_ResultConstruction(aFromResult).shape()
 anExtrusionCutFt.selection("from_object").setValue(aFromResult, aFromShape)
 anExtrusionCutFt.real("from_offset").setValue(0)
-anExtrusionCutFt.selectionList("main_objects").append(modelAPI_ResultCompSolid(anExtrusionResult).subResult(1), None)
+anExtrusionCutFt.selectionList("main_objects").append(anExtrusionResult.subResult(1), None)
 aSession.finishOperation()
 aSession.finishOperation()
 
@@ -232,7 +232,7 @@ anRevolutionFuseFt.selection("to_object").setValue(aToResult, None)
 anRevolutionFuseFt.real("to_offset").setValue(0)
 anRevolutionFuseFt.selection("from_object").setValue(None, None)
 anRevolutionFuseFt.real("from_offset").setValue(0)
-anRevolutionFuseFt.selectionList("main_objects").append(modelAPI_ResultCompSolid(anExtrusionResult).subResult(1), None)
+anRevolutionFuseFt.selectionList("main_objects").append(anExtrusionResult.subResult(1), None)
 aSession.finishOperation()
 aSession.finishOperation()
 
index 9a10cfab5d2b3a8fdf17d678fb9761f628e893a1..7926781a667b9032710db3da016238bb6820eb3f 100644 (file)
@@ -79,7 +79,7 @@ anExtrusionFeature.real("to_offset").setValue(0) #TODO: remove
 anExtrusionFeature.real("from_offset").setValue(0) #TODO: remove
 anExtrusionFeature.execute()
 aSession.finishOperation()
-anExtrusionResult = modelAPI_ResultCompSolid(modelAPI_ResultBody(anExtrusionFeature.firstResult()))
+anExtrusionResult = modelAPI_ResultBody(anExtrusionFeature.firstResult())
 
 #=========================================================================
 # Remove sub-shapes
@@ -91,7 +91,7 @@ aRemoveSubShapesFeature.string("creation_method").setValue("by_keep_subshapes")
 aRemoveSubShapesFeature.selectionList("subshapes_to_keep").removeLast();
 aSession.finishOperation()
 assert (len(aRemoveSubShapesFeature.results()) > 0)
-anUnionResult = modelAPI_ResultCompSolid(modelAPI_ResultBody(aRemoveSubShapesFeature.firstResult()))
+anUnionResult = modelAPI_ResultBody(aRemoveSubShapesFeature.firstResult())
 assert (anUnionResult.numberOfSubs() == 2)
 
 from salome.shaper import model
index fa540f7f2b018fbe2cdd9226656eeb5e1aa77716..541ad7344a0088c86295effa6699463e94e7246a 100644 (file)
@@ -79,7 +79,7 @@ anExtrusionFeature.real("to_offset").setValue(0) #TODO: remove
 anExtrusionFeature.real("from_offset").setValue(0) #TODO: remove
 anExtrusionFeature.execute()
 aSession.finishOperation()
-anExtrusionResult = modelAPI_ResultCompSolid(modelAPI_ResultBody(anExtrusionFeature.firstResult()))
+anExtrusionResult = modelAPI_ResultBody(anExtrusionFeature.firstResult())
 
 #=========================================================================
 # Make union on extrusion
@@ -91,7 +91,7 @@ aUnionFeature.selectionList("base_objects").append(anExtrusionResult.subResult(1
 aUnionFeature.selectionList("base_objects").append(anExtrusionResult.subResult(2), None);
 aSession.finishOperation()
 assert (len(aUnionFeature.results()) > 0)
-anUnionResult = modelAPI_ResultCompSolid(modelAPI_ResultBody(aUnionFeature.firstResult()))
+anUnionResult = modelAPI_ResultBody(aUnionFeature.firstResult())
 assert (anUnionResult.numberOfSubs() == 0)
 
 from salome.shaper import model
index 5d71673a7de8f69e29714789cf05303a3257ba07..d441758f83bcda965ccb96a8a63cdf1d373fa1c8 100644 (file)
@@ -60,7 +60,6 @@ SET(PROJECT_HEADERS
     GeomAPI_Ellipse.h
     GeomAPI_Ellipse2d.h
     GeomAPI_Tools.h
-    GeomAPI_IScreenParams.h
     GeomAPI_Shell.h
     GeomAPI_Solid.h
     GeomAPI_Sphere.h
index bcfae3effe85aa00701b7cf8094d295dba1dc549..ff040cecb1c5e1965e47445620e8d830e2182605 100644 (file)
@@ -26,6 +26,7 @@
 #include <ModelAPI_Object.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Tools.h>
+#include <ModelAPI_ResultBody.h>
 
 bool GeomValidators_BodyShapes::isValid(const AttributePtr& theAttribute,
                                         const std::list<std::string>& theArguments,
@@ -36,21 +37,36 @@ bool GeomValidators_BodyShapes::isValid(const AttributePtr& theAttribute,
     AttributeSelectionPtr anAttrSelection =
       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
     ResultPtr aContext = anAttrSelection->context();
-    if(!aContext.get()) {
+    FeaturePtr aContextFeature = anAttrSelection->contextFeature();
+    if (!(aContext.get() || aContextFeature.get())) {
       theError = "Error: Context is empty.";
       return false;
     }
-
-    ResultConstructionPtr aResultConstruction =
-      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
-    if(aResultConstruction.get()) {
-      theError = "Error: Result construction selected.";
-      return false;
-    }
-    // additional check that the selected object is top-level result
-    if (theArguments.size() > 0 && *(theArguments.rbegin()) == "toplevel") {
-      if (ModelAPI_Tools::compSolidOwner(aContext).get()) {
-        theError = "Error: Only higher level shape allowed.";
+    if (aContext.get()) {
+      ResultConstructionPtr aResultConstruction =
+        std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+      if (aResultConstruction.get()) {
+        theError = "Error: Result construction selected.";
+        return false;
+      }
+      // additional check that the selected object is top-level result
+      if (theArguments.size() > 0 && *(theArguments.rbegin()) == "toplevel") {
+        if (ModelAPI_Tools::bodyOwner(aContext).get()) {
+          theError = "Error: Only higher level shape allowed.";
+          return false;
+        }
+      }
+    } else {
+      std::list<ResultPtr> aResList = aContextFeature->results();
+      std::list<ResultPtr>::const_iterator aIt;
+      for (aIt = aResList.cbegin(); aIt != aResList.cend(); aIt++) {
+        ResultPtr aRes = (*aIt);
+        ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aRes);
+        if (aBody.get())
+          break;
+      }
+      if (aIt == aResList.cend()) {
+        theError = "Error: Feature doesn't creates body.";
         return false;
       }
     }
diff --git a/src/GeomValidators/GeomValidators_IntersectionSelection.cpp b/src/GeomValidators/GeomValidators_IntersectionSelection.cpp
new file mode 100644 (file)
index 0000000..fe437a0
--- /dev/null
@@ -0,0 +1,99 @@
+// 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 "GeomValidators_IntersectionSelection.h"
+
+#include <GeomAPI_Shape.h>
+
+#include <Events_InfoMessage.h>
+
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Feature.h>
+
+bool GeomValidators_IntersectionSelection::isValid(const AttributePtr& theAttribute,
+                                                   const std::list<std::string>& theArguments,
+                                                   Events_InfoMessage& theError) const
+{
+  if(!theAttribute.get()) {
+    theError = "Error: empty selection.";
+    return false;
+  }
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+  AttributeSelectionListPtr anAttrSelectionList =
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+    if(!anAttrSelection.get()) {
+      theError = "Error: empty attribute selection.";
+      return false;
+    }
+    FeaturePtr aFeature;
+    ResultPtr aContext = anAttrSelection->context();
+    if(!aContext.get()) {
+      aFeature = anAttrSelection->contextFeature();
+      if (!aFeature.get()) {
+        theError = "Error: Empty selection context.";
+        return false;
+      }
+    } else {
+      aFeature = ModelAPI_Feature::feature(aContext);
+    }
+
+    if(!aFeature.get()) {
+      theError = "Error: empty feature.";
+      return false;
+    }
+    std::string aFeatureKind = aFeature->getKind();
+    if(aFeatureKind == "Sketch" ||
+       aFeatureKind == "Plane" ||
+       aFeatureKind == "Axis") {
+      theError = "Error: %1 shape is not allowed for selection.";
+      theError.arg(aFeatureKind);
+      return false;
+    }
+    std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
+    GeomShapePtr aContextShape = aContext->shape();
+    if(!aShape.get()) {
+      aShape = aContextShape;
+    }
+    if(!aShape.get()) {
+      theError = "Error: empty shape.";
+      return false;
+    }
+    if(!aShape->isEqual(aContextShape)) {
+      theError = "Error: Local selection not allowed.";
+      return false;
+    }
+
+    int aShapeType = aShape->shapeType();
+    // Allow to select edges, faces and solids.
+    if(aShapeType != GeomAPI_Shape::EDGE &&
+       aShapeType != GeomAPI_Shape::FACE &&
+       aShapeType != GeomAPI_Shape::SOLID &&
+       aShapeType != GeomAPI_Shape::COMPSOLID &&
+       aShapeType != GeomAPI_Shape::COMPOUND) {
+      theError = "Error: selected shape has the wrong type.";
+      return false;
+    }
+  }
+
+  return true;
+}
index 3ee016de3709faea44c4184fa406ce640c623983..afb7dd0c93eb2c6a5bb6eefa2965bd750a5b698b 100755 (executable)
@@ -25,6 +25,7 @@
 #include <GeomDataAPI_Point2D.h>
 
 #include <ModelAPI_Result.h>
+#include <ModelAPI_Feature.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeSelectionList.h>
@@ -130,8 +131,12 @@ bool GeomValidators_ShapeType::isValidAttribute(const AttributePtr& theAttribute
     GeomShapePtr aShape = anAttr->value();
     if (aShape.get())
       aValid = isValidShape(aShape, theShapeType, theError);
-    else
-      aValid = isValidObject(anAttr->context(), theShapeType, theError);
+    else {
+      if (anAttr->context().get())
+        aValid = isValidObject(anAttr->context(), theShapeType, theError);
+      else
+        aValid = isValidObject(anAttr->contextFeature(), theShapeType, theError);
+    }
   }
   else if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
     AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
@@ -178,6 +183,8 @@ bool GeomValidators_ShapeType::isValidAttribute(const AttributePtr& theAttribute
     theError = "The attribute with the %1 type is not processed";
     theError.arg(anAttributeType);
   }
+  if (aValid)
+    theError = "";
   return aValid;
 }
 
@@ -194,20 +201,29 @@ bool GeomValidators_ShapeType::isValidObject(const ObjectPtr& theObject,
   }
   else {
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
-    if( theShapeType==Plane )
-    {
-      ResultConstructionPtr aResultConstruction =
-        std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theObject);
-      FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
-      const std::string& aKind = aFeature->getKind();
-      return aResult.get() != NULL && aKind == "Plane";
-    }
-    if (!aResult.get()) {
-      aValid = false;
-      theError = "The result is empty";
-    }
-    else {
-      aValid = isValidShape(aResult->shape(), theShapeType, theError);
+    if (aResult.get()) {
+      if (theShapeType == Plane)
+      {
+        ResultConstructionPtr aResultConstruction =
+          std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theObject);
+        FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+        const std::string& aKind = aFeature->getKind();
+        return aResult.get() != NULL && aKind == "Plane";
+      }
+      if (!aResult.get()) {
+        aValid = false;
+        theError = "The result is empty";
+      } else {
+        aValid = isValidShape(aResult->shape(), theShapeType, theError);
+      }
+    } else {
+      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+      if (aFeature.get() && (theShapeType == CompSolid))
+        return aValid;
+      else {
+        aValid = false;
+        theError = "The feature has to produce a compsolid";
+      }
     }
   }
   return aValid;
index 37dfcb27424d05e826b24dacfaca1fde0304ef0d..cacba22ced29ee99dcdf0d44bbaada591ef5c69c 100644 (file)
@@ -48,7 +48,6 @@ SET(PROJECT_HEADERS
     Model_Update.h
     Model_Validator.h
     Model_ResultBody.h
-    Model_ResultCompSolid.h
     Model_ResultConstruction.h
     Model_ResultPart.h
     Model_ResultField.h
@@ -86,7 +85,6 @@ SET(PROJECT_SOURCES
     Model_Update.cpp
     Model_Validator.cpp
     Model_ResultBody.cpp
-    Model_ResultCompSolid.cpp
     Model_ResultConstruction.cpp
     Model_ResultPart.cpp
     Model_ResultField.cpp
index dd63dcf225f0a9011c74162de9e1b73ffe4db9f4..1be7f53ee6a44491185f482f3923fc695adca38d 100644 (file)
@@ -29,7 +29,7 @@
 #include <Model_ResultConstruction.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_CompositeFeature.h>
@@ -39,6 +39,7 @@
 #include <Events_InfoMessage.h>
 #include <GeomAPI_Edge.h>
 #include <GeomAPI_Vertex.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
 
 #include <TNaming_Selector.hxx>
 #include <TNaming_NamedShape.hxx>
@@ -85,17 +86,22 @@ Standard_GUID kELLIPSE_CENTER1("f70df04c-3168-4dc9-87a4-f1f840c1275d");
 // identifier of the selection of the second focus point of ellipse on edge
 Standard_GUID kELLIPSE_CENTER2("1395ae73-8e02-4cf8-b204-06ff35873a32");
 
+// prefix for the whole feature context identification
+const static std::string kWHOLE_FEATURE = "all-in-";
+
 // on this label is stored:
 // TNaming_NamedShape - selected shape
 // TNaming_Naming - topological selection information (for the body)
 // TDataStd_IntPackedMap - indexes of edges in composite element (for construction)
 // TDataStd_Integer - type of the selected shape (for construction)
 // TDF_Reference - from ReferenceAttribute, the context
-bool Model_AttributeSelection::setValue(const ResultPtr& theContext,
+bool Model_AttributeSelection::setValue(const ObjectPtr& theContext,
   const std::shared_ptr<GeomAPI_Shape>& theSubShape, const bool theTemporarily)
 {
-  if (theTemporarily) { // just keep the stored without DF update
-    myTmpContext = theContext;
+  if (theTemporarily &&
+      (!theContext.get() || theContext->groupName() != ModelAPI_Feature::group())) {
+    // just keep the stored without DF update
+    myTmpContext = std::dynamic_pointer_cast<ModelAPI_Result>(theContext);
     myTmpSubShape = theSubShape;
     owner()->data()->sendAttributeUpdated(this);
     return true;
@@ -143,34 +149,37 @@ bool Model_AttributeSelection::setValue(const ResultPtr& theContext,
     return false;
   }
   if (theContext->groupName() == ModelAPI_ResultBody::group()) {
+    ResultBodyPtr aContextBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theContext);
     // do not select the whole shape for body:it is already must be in the data framework
     // equal and null selected objects mean the same: object is equal to context,
-    if (theContext->shape().get() &&
-        (theContext->shape()->isEqual(theSubShape) || !theSubShape.get())) {
+    if (aContextBody->shape().get() &&
+        (aContextBody->shape()->isEqual(theSubShape) || !theSubShape.get())) {
       aSelLab.ForgetAllAttributes(true);
       TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID);
     } else {
-      selectBody(theContext, theSubShape);
+      selectBody(aContextBody, theSubShape);
     }
   } else if (theContext->groupName() == ModelAPI_ResultConstruction::group()) {
+    ResultConstructionPtr aContextConstruction =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theContext);
     aSelLab.ForgetAllAttributes(true); // to remove old selection data
     std::shared_ptr<Model_ResultConstruction> aConstruction =
       std::dynamic_pointer_cast<Model_ResultConstruction>(theContext);
     std::shared_ptr<GeomAPI_Shape> aSubShape;
-    if (theSubShape.get() && !theContext->shape()->isEqual(theSubShape))
+    if (theSubShape.get() && !aContextConstruction->shape()->isEqual(theSubShape))
       aSubShape = theSubShape; // the whole context
     if (aConstruction->isInfinite()) {
       // For correct naming selection, put the shape into the naming structure.
       // It seems sub-shapes are not needed: only this shape is (and can be ) selected.
       TNaming_Builder aBuilder(aSelLab);
-      aBuilder.Generated(theContext->shape()->impl<TopoDS_Shape>());
+      aBuilder.Generated(aContextConstruction->shape()->impl<TopoDS_Shape>());
     }
     int anIndex = aConstruction->select(theSubShape, owner()->document());
     TDataStd_Integer::Set(aSelLab, anIndex);
   } else if (theContext->groupName() == ModelAPI_ResultPart::group()) {
     aSelLab.ForgetAllAttributes(true);
     TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID);
-    selectPart(theContext, theSubShape);
+    selectPart(std::dynamic_pointer_cast<ModelAPI_Result>(theContext), theSubShape);
   }
 
   owner()->data()->sendAttributeUpdated(this);
@@ -182,7 +191,7 @@ bool Model_AttributeSelection::setValue(const ResultPtr& theContext,
 }
 
 void Model_AttributeSelection::setValueCenter(
-    const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
+    const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
     const CenterType theCenterType, const bool theTemporarily)
 {
   bool anUpdated = setValue(theContext, theEdge, theTemporarily);
@@ -344,6 +353,22 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::internalValue(CenterTyp
       if (aConstr->isInfinite())
         return aResult; // empty result
     }
+    // whole feature
+    FeaturePtr aFeature = contextFeature();
+    if (aFeature.get()) {
+      std::list<GeomShapePtr> allShapes;
+      std::list<ResultPtr>::const_iterator aRes = aFeature->results().cbegin();
+      for (; aRes != aFeature->results().cend(); aRes++) {
+        if (aRes->get() && !(*aRes)->isDisabled()) {
+          GeomShapePtr aShape = (*aRes)->shape();
+          if (aShape.get() && !aShape->isNull()) {
+            allShapes.push_back(aShape);
+          }
+        }
+      }
+      return GeomAlgoAPI_CompoundBuilder::compound(allShapes);
+    }
+
     Handle(TNaming_NamedShape) aSelection;
     if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
       TopoDS_Shape aSelShape = aSelection->Get();
@@ -389,6 +414,10 @@ bool Model_AttributeSelection::isInitialized()
             return true;
           }
         }
+        // for the whole feature, a feature object
+        FeaturePtr aFeat = contextFeature();
+        if (aFeat.get())
+          return true;
       }
     }
   }
@@ -436,6 +465,19 @@ ResultPtr Model_AttributeSelection::context()
   return aResult;
 }
 
+FeaturePtr Model_AttributeSelection::contextFeature() {
+  if (myTmpContext.get() || myTmpSubShape.get()) {
+    return FeaturePtr(); // feature can not be selected temporarily
+  }
+  return std::dynamic_pointer_cast<ModelAPI_Feature>(myRef.value());
+}
+ObjectPtr Model_AttributeSelection::contextObject() {
+  ResultPtr aRes = context();
+  if (aRes.get())
+    return aRes;
+  return contextFeature();
+}
+
 
 void Model_AttributeSelection::setObject(const std::shared_ptr<ModelAPI_Object>& theObject)
 {
@@ -681,8 +723,10 @@ void Model_AttributeSelection::selectBody(
     }
     if (!isFound) { // sub-shape is not found in the up-to-date instance of the context shape
       // if context is sub-result of compound/compsolid, selection of sub-shape better propagate to
-      // the main result (which is may be modified), case is in 1799
-      ResultCompSolidPtr aMain = ModelAPI_Tools::compSolidOwner(theContext);
+      // the main result (which is may be modified); the case is in 1799
+      ResultBodyPtr aMain = ModelAPI_Tools::bodyOwner(theContext);
+      while(ModelAPI_Tools::bodyOwner(aMain).get())
+        aMain = ModelAPI_Tools::bodyOwner(theContext);
       if (aMain.get()) {
         selectBody(aMain, theSubShape);
         return;
@@ -780,8 +824,15 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa
   std::shared_ptr<GeomAPI_Shape> aSubSh = internalValue(aCenterType);
   ResultPtr aCont = context();
 
-  if (!aCont.get()) // in case of selection of removed result
+  if (!aCont.get()) {
+    // selection of a full feature
+    FeaturePtr aFeatureCont = contextFeature();
+    if (aFeatureCont.get()) {
+      return kWHOLE_FEATURE + aFeatureCont->name();
+    }
+    // in case of selection of removed result
     return "";
+  }
 
   Model_SelectionNaming aSelNaming(selectionLabel());
   std::string aResult = aSelNaming.namingName(
@@ -852,9 +903,21 @@ void Model_AttributeSelection::selectSubShape(
       }
     }
 
-    Model_SelectionNaming aSelNaming(selectionLabel());
     std::shared_ptr<Model_Document> aDoc =
       std::dynamic_pointer_cast<Model_Document>(owner()->document());
+    // check this is a whole feature context
+    if (aSubShapeName.size() > kWHOLE_FEATURE.size() &&
+      aSubShapeName.substr(0, kWHOLE_FEATURE.size()) == kWHOLE_FEATURE) {
+      std::string aFeatureName = aSubShapeName.substr(kWHOLE_FEATURE.size());
+      ObjectPtr anObj = aDoc->objectByName(ModelAPI_Feature::group(), aFeatureName);
+      if (anObj.get()) {
+        static const GeomShapePtr anEmptyShape;
+        setValue(anObj, anEmptyShape);
+        return;
+      }
+    }
+
+    Model_SelectionNaming aSelNaming(selectionLabel());
     std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected;
     ResultPtr aCont;
     if (aSelNaming.selectSubShape(aType, aSubShapeName, aDoc, aShapeToBeSelected, aCont)) {
@@ -868,9 +931,14 @@ void Model_AttributeSelection::selectSubShape(
             aNS = TNaming_Tool::CurrentNamedShape(aNS);
             if (!aNS.IsNull() && scope().Contains(aNS->Label())) { // scope check is for 2228
               TDF_Label aLab = aNS->Label();
-              while(aLab.Depth() != 7 && aLab.Depth() > 5)
+              if (aLab.Depth() % 2 == 0)
                 aLab = aLab.Father();
               ObjectPtr anObj = aDoc->objects()->object(aLab);
+              while(!anObj.get() && aLab.Depth() > 5) {
+                aLab = aLab.Father().Father();
+                anObj = aDoc->objects()->object(aLab);
+              }
+
               if (anObj.get()) {
                 ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
                 if (aRes)
@@ -882,11 +950,15 @@ void Model_AttributeSelection::selectSubShape(
       }
       // if compsolid is context, try to take sub-solid as context: like in GUI and scripts
       if (aCont.get() && aShapeToBeSelected.get()) {
-        ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aCont);
+        ResultBodyPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aCont);
         if (aComp && aComp->numberOfSubs()) {
-          for(int aSubNum = 0; aSubNum < aComp->numberOfSubs(); aSubNum++) {
-            ResultPtr aSub = aComp->subResult(aSubNum);
-            if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aShapeToBeSelected)) {
+          std::list<ResultPtr> allSubs;
+          ModelAPI_Tools::allSubs(aComp, allSubs);
+          std::list<ResultPtr>::iterator aS = allSubs.begin();
+          for(; aS != allSubs.end(); aS++) {
+            ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aS);
+            if (aSub && aSub->numberOfSubs() == 0 && aSub->shape().get() &&
+                aSub->shape()->isSubShape(aShapeToBeSelected)) {
               aCont = aSub;
               break;
             }
@@ -899,14 +971,20 @@ void Model_AttributeSelection::selectSubShape(
       while(aFindNewContext && aCont.get()) {
         aFindNewContext = false;
         // take references to all results: root one, any sub
-        ResultCompSolidPtr aCompContext = ModelAPI_Tools::compSolidOwner(aCont);
-        int aSubsSize = (aCompContext.get() ? aCompContext->numberOfSubs() : 0) + 1;
-        for(int aResultNum = 0; aResultNum < aSubsSize; aResultNum++) {
-          ResultPtr aResCont = aCont;
-          if (aCompContext.get())
-            if (aResultNum == aSubsSize - 1)
-              aResCont = aCompContext;
-            else aResCont = aCompContext->subResult(aResultNum);
+        ResultBodyPtr aCompContext = ModelAPI_Tools::bodyOwner(aCont, true);
+        std::list<ResultPtr> allRes;
+        if (aCompContext.get()) {
+          ModelAPI_Tools::allSubs(aCompContext, allRes);
+          allRes.push_back(aCompContext);
+        } else {
+          allRes.push_back(aCont);
+        }
+        for(std::list<ResultPtr>::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) {
+          ResultPtr aResCont = *aSub;
+          ResultBodyPtr aResBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResCont);
+          // only lower and higher level subs are counted
+          if (aResBody.get() && aResBody->numberOfSubs() > 0 && aResBody != aCompContext)
+            continue;
           const std::set<AttributePtr>& aRefs = aResCont->data()->refsToMe();
           std::set<AttributePtr>::const_iterator aRef = aRefs.begin();
           for(; !aFindNewContext && aRef != aRefs.end(); aRef++) {
@@ -921,20 +999,13 @@ void Model_AttributeSelection::selectSubShape(
             std::list<std::shared_ptr<ModelAPI_Result> > aResults;
 
             // take all sub-results or one result
-            const std::list<std::shared_ptr<ModelAPI_Result> >& aFResults = aRefFeat->results();
-            std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aFResults.begin();
-            for (; aRIter != aFResults.cend(); aRIter++) {
-              // iterate sub-bodies of compsolid
-              ResultCompSolidPtr aComp =
-                std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aRIter);
-              if (aComp.get() && aComp->numberOfSubs() > 0) {
-                int aNumSub = aComp->numberOfSubs();
-                for(int a = 0; a < aNumSub; a++) {
-                  aResults.push_back(aComp->subResult(a));
-                }
-              } else {
-                aResults.push_back(*aRIter);
-              }
+            std::list<ResultPtr> aRefFeatResults;
+            ModelAPI_Tools::allResults(aRefFeat, aRefFeatResults);
+            std::list<ResultPtr>::iterator aRefResIter = aRefFeatResults.begin();
+            for(; aRefResIter != aRefFeatResults.end(); aRefResIter++) {
+              ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRefResIter);
+              if (aBody.get() && aBody->numberOfSubs() == 0) // add only lower level subs
+                aResults.push_back(aBody);
             }
             std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = aResults.begin();
             for(; aResIter != aResults.end(); aResIter++) {
@@ -945,8 +1016,6 @@ void Model_AttributeSelection::selectSubShape(
                 aShapeToBeSelected.get() ? aShapeToBeSelected : aCont->shape();
               if (aShape.get() && aShape->isSubShape(aSelectedShape, false)) {
                 aCont = *aResIter; // found new context (produced from this) with same subshape
-                //if (!aShape->isSubShape(aShapeToBeSelected, true)) // take context orientation
-                //  aShapeToBeSelected->setOrientation();
                 aFindNewContext = true; // continue searching futher
                 break;
               }
@@ -975,17 +1044,18 @@ int Model_AttributeSelection::Id()
 {
   int anID = 0;
   std::shared_ptr<GeomAPI_Shape> aSelection = value();
-  std::shared_ptr<GeomAPI_Shape> aContext = context()->shape();
+  ResultPtr aContextRes = context();
   // support for compsolids:
-  if (context().get() && ModelAPI_Tools::compSolidOwner(context()).get())
-    aContext = ModelAPI_Tools::compSolidOwner(context())->shape();
+  while(ModelAPI_Tools::bodyOwner(aContextRes).get()) {
+    aContextRes = ModelAPI_Tools::bodyOwner(aContextRes);
+  }
+  std::shared_ptr<GeomAPI_Shape> aContext = aContextRes->shape();
 
 
   TopoDS_Shape aMainShape = aContext->impl<TopoDS_Shape>();
   const TopoDS_Shape& aSubShape = aSelection->impl<TopoDS_Shape>();
   // searching for the latest main shape
-  if (aSelection && !aSelection->isNull() &&
-    aContext   && !aContext->isNull())
+  if (aSelection && !aSelection->isNull() && aContext && !aContext->isNull())
   {
     std::shared_ptr<Model_Document> aDoc =
       std::dynamic_pointer_cast<Model_Document>(context()->document());
@@ -1005,21 +1075,21 @@ int Model_AttributeSelection::Id()
 
 void Model_AttributeSelection::setId(int theID)
 {
-  const ResultPtr& aContext = context();
   std::shared_ptr<GeomAPI_Shape> aSelection;
 
-  std::shared_ptr<GeomAPI_Shape> aContextShape = aContext->shape();
+  ResultPtr aContextRes = context();
   // support for compsolids:
-  if (aContext.get() && ModelAPI_Tools::compSolidOwner(aContext).get())
-    aContextShape = ModelAPI_Tools::compSolidOwner(aContext)->shape();
+  while(ModelAPI_Tools::bodyOwner(aContextRes).get()) {
+    aContextRes = ModelAPI_Tools::bodyOwner(aContextRes);
+  }
+  std::shared_ptr<GeomAPI_Shape> aContext = aContextRes->shape();
 
-  TopoDS_Shape aMainShape = aContextShape->impl<TopoDS_Shape>();
+  TopoDS_Shape aMainShape = aContext->impl<TopoDS_Shape>();
   // searching for the latest main shape
-  if (theID > 0 &&
-      aContextShape && !aContextShape->isNull())
+  if (theID > 0 && aContext && !aContext->isNull())
   {
     std::shared_ptr<Model_Document> aDoc =
-      std::dynamic_pointer_cast<Model_Document>(aContext->document());
+      std::dynamic_pointer_cast<Model_Document>(aContextRes->document());
     if (aDoc.get()) {
       Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aMainShape, aDoc->generalLabel());
       if (!aNS.IsNull()) {
@@ -1037,7 +1107,7 @@ void Model_AttributeSelection::setId(int theID)
     aSelection = aResult;
   }
 
-  setValue(aContext, aSelection);
+  setValue(aContextRes, aSelection);
 }
 
 std::string Model_AttributeSelection::contextName(const ResultPtr& theContext) const
@@ -1085,10 +1155,16 @@ void Model_AttributeSelection::computeValues(
   // if new context becomes compsolid, the resulting sub may be in sub-solids
   std::list<ResultPtr> aNewToIterate;
   aNewToIterate.push_back(theNewContext);
-  ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theNewContext);
+  ResultBodyPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theNewContext);
   if (aComp.get()) {
-    for(int a = 0; a < aComp->numberOfSubs(); a++)
-      aNewToIterate.push_back(aComp->subResult(a, false));
+    std::list<ResultPtr> allNewContextSubs;
+    ModelAPI_Tools::allSubs(aComp, allNewContextSubs);
+    std::list<ResultPtr>::iterator aSub = allNewContextSubs.begin();
+    for(; aSub != allNewContextSubs.end(); aSub++) {
+      ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSub);
+      if (aBody.get() && aBody->numberOfSubs() == 0) // add only lower level subs
+        aNewToIterate.push_back(aBody);
+    }
   }
 
   // first iteration: searching for the whole shape appearance (like face of the box)
@@ -1173,7 +1249,7 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
   TopTools_ListOfShape aContextList;
   aContextList.Append(theContShape);
   if (theContext.get()) {
-    ResultPtr aComposite = ModelAPI_Tools::compSolidOwner(theContext);
+    ResultPtr aComposite = ModelAPI_Tools::bodyOwner(theContext);
     if (aComposite.get() && aComposite->shape().get() && !aComposite->shape()->isNull())
       aContextList.Append(aComposite->shape()->impl<TopoDS_Shape>());
   }
index 5306aa68df25b65573dc303b3006dee5c57e8528..9267748a7d33a4e182726643cbb3d2404f94f320 100644 (file)
@@ -55,13 +55,13 @@ public:
   ///           (used to remove immideately, without the following updates)
   /// \returns true if attribute was updated
   MODEL_EXPORT virtual bool setValue(
-    const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
+    const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
     const bool theTemporarily = false);
 
   /// Same as SetValue, but it takes an edge (on circular or elliptical curve)
   /// and stores the vertex of the central point (for ellipse the first or the second focus point)
   MODEL_EXPORT virtual void setValueCenter(
-    const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
+    const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
     const CenterType theCenterType,
     const bool theTemporarily = false);
 
@@ -78,6 +78,11 @@ public:
   /// Returns the context of the selection (the whole shape owner)
   MODEL_EXPORT virtual ResultPtr context();
 
+  /// Returns the context of the selection if the whole feature was selected
+  MODEL_EXPORT virtual FeaturePtr contextFeature();
+  /// Returns the context of the selection : result or feature
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Object> contextObject();
+
   /// Sets the feature object
   MODEL_EXPORT virtual void setObject(const std::shared_ptr<ModelAPI_Object>& theObject);
 
index 5207a112024deb535b0e860b5e072f7b7dea05e5..bc1c7f1172376ea7164b04ee6d2664a132d494ac 100644 (file)
@@ -41,7 +41,7 @@
 #include <NCollection_List.hxx>
 
 void Model_AttributeSelectionList::append(
-    const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
+    const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
     const bool theTemporarily)
 {
   // do not use the degenerated edge as a shape, a list is not incremented in this case
@@ -53,7 +53,9 @@ void Model_AttributeSelectionList::append(
   }
 
   if (myIsCashed && !theTemporarily) {
-    myCash[theContext].push_back(theSubShape);
+    ResultPtr aResContext = std::dynamic_pointer_cast<ModelAPI_Result>(theContext);
+    if (aResContext.get())
+      myCash[aResContext].push_back(theSubShape);
   }
 
   int aNewTag = mySize->Get() + 1;
@@ -225,28 +227,31 @@ int Model_AttributeSelectionList::size()
   return mySize->Get();
 }
 
-bool Model_AttributeSelectionList::isInList(const ResultPtr& theContext,
+bool Model_AttributeSelectionList::isInList(const ObjectPtr& theContext,
                                             const std::shared_ptr<GeomAPI_Shape>& theSubShape,
                                             const bool theTemporarily)
 {
+  ResultPtr aResCont = std::dynamic_pointer_cast<ModelAPI_Result>(theContext);
   if (myIsCashed) { // the cashing is active
-    std::map<ResultPtr, std::list<std::shared_ptr<GeomAPI_Shape> > >::iterator aContext =
-      myCash.find(theContext);
-    if (aContext != myCash.end()) {
-      // iterate shapes because "isSame" method must be called for each shape
-      std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aShapes = aContext->second.begin();
-      for(; aShapes != aContext->second.end(); aShapes++) {
-        if (!theSubShape.get()) {
-          if (!aShapes->get() || (*aShapes)->isSame(aContext->first->shape()))
-            return true;
-        } else {
-          // we need to call here isSame instead of isEqual to do not check shapes orientation
-          if (theSubShape->isSame(*aShapes))
-            return true;
+    if (aResCont.get()) {
+      std::map<ResultPtr, std::list<std::shared_ptr<GeomAPI_Shape> > >::iterator aContext =
+        myCash.find(aResCont);
+      if (aContext != myCash.end()) {
+        // iterate shapes because "isSame" method must be called for each shape
+        std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aShapes = aContext->second.begin();
+        for(; aShapes != aContext->second.end(); aShapes++) {
+          if (!theSubShape.get()) {
+            if (!aShapes->get() || (*aShapes)->isSame(aContext->first->shape()))
+              return true;
+          } else {
+            // we need to call here isSame instead of isEqual to do not check shapes orientation
+            if (theSubShape->isSame(*aShapes))
+              return true;
+          }
         }
       }
+      return false;
     }
-    return false;
   }
   // no-cash method
   for(int anIndex = size() - 1; anIndex >= 0; anIndex--) {
@@ -255,7 +260,7 @@ bool Model_AttributeSelectionList::isInList(const ResultPtr& theContext,
       if (anAttr->context() == theContext) { // contexts are equal, so, check that values are also
         std::shared_ptr<GeomAPI_Shape> aValue = anAttr->value();
         if (!theSubShape.get()) {
-          if (!aValue.get() || aValue->isSame(theContext->shape())) { // both are null
+          if (!aValue.get() || (aResCont.get() && aValue->isSame(aResCont->shape()))) {// both null
             return true;
           }
         } else {
index fd37b734b33ce564c09a8f44179b6923c10be103..289534c62e340b5a03004332e73c51e7b7846d04 100644 (file)
@@ -52,7 +52,7 @@ public:
   /// \param theTemporarily if it is true, do not store and name the added in the data framework
   ///           (used to remove immideately, without the following updates)
   MODEL_EXPORT virtual void append(
-    const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
+    const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
     const bool theTemporarily = false);
 
   /// Adds the new reference to the end of the list by the naming name of the selected shape
@@ -78,7 +78,7 @@ public:
   /// \param theTemporarily if it is true, it checks also the temporary added item
   /// \returns true if the pair is found in the attirbute
   MODEL_EXPORT virtual bool isInList(
-    const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
+    const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
     const bool theTemporarily = false);
 
   /// The type of all elements selection
index ab2c1dec6e37483221a8f54ac486cc68fd8cf729..c301d069454f987074caa7b9b4cc88d671837944 100755 (executable)
@@ -129,7 +129,7 @@ static void evolutionToSelectionRec(TDF_Label theLab, const bool theFlag) {
 void Model_BodyBuilder::evolutionToSelection(const bool theFlag)
 {
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
-  if (!aData) // unknown case
+  if (!aData || !aData->isValid()) // unknown case
     return;
   TDF_Label& aShapeLab = aData->shapeLab();
   evolutionToSelectionRec(aShapeLab, theFlag);
@@ -1107,7 +1107,7 @@ void Model_BodyBuilder::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape>
 std::shared_ptr<GeomAPI_Shape> Model_BodyBuilder::shape()
 {
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
-  if (aData) {
+  if (aData && aData->isValid()) {
     TDF_Label aShapeLab = aData->shapeLab();
     Handle(TDF_Reference) aRef;
     if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
index a863d55dd6a961c44a7277cd50ca3923c512b15f..74f19ec71f3b4bb90ba4b8ceaccb51e57392fb78 100644 (file)
@@ -42,7 +42,6 @@
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_ResultPart.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_Tools.h>
 #include <Model_Validator.h>
 
@@ -139,7 +138,7 @@ void Model_Data::setName(const std::string& theName)
       bool isUserDefined = true;
       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
       if (aResult) {
-        std::string aDefaultName = ModelAPI_Tools::getDefaultName(aResult);
+        std::string aDefaultName = ModelAPI_Tools::getDefaultName(aResult, false).first;
         isUserDefined = aDefaultName != theName;
       }
       if (isUserDefined) {
@@ -485,10 +484,10 @@ int Model_Data::featureId() const
 void Model_Data::eraseBackReferences()
 {
   myRefsToMe.clear();
-  std::shared_ptr<ModelAPI_Result> aRes =
-    std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
-  if (aRes)
+  std::shared_ptr<ModelAPI_Result> aRes = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
+  if (aRes) {
     aRes->setIsConcealed(false);
+  }
 }
 
 void Model_Data::removeBackReference(ObjectPtr theObject, std::string theAttrID)
@@ -519,8 +518,7 @@ void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID,
 
   if (theApplyConcealment &&  theFeature->isStable() &&
       ModelAPI_Session::get()->validators()->isConcealed(theFeature->getKind(), theAttrID)) {
-    std::shared_ptr<ModelAPI_Result> aRes =
-      std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
+    std::shared_ptr<ModelAPI_Result> aRes = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
     // the second condition is for history upper than concealment causer, so the feature result may
     // be displayed and previewed; also for avoiding of quick show/hide on history
     // moving deep down
@@ -547,8 +545,7 @@ void Model_Data::updateConcealmentFlag()
       if (aFeature.get() && !aFeature->isDisabled() && aFeature->isStable()) {
         if (ModelAPI_Session::get()->validators()->isConcealed(
               aFeature->getKind(), (*aRefsIter)->id())) {
-          std::shared_ptr<ModelAPI_Result> aRes =
-            std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
+          std::shared_ptr<ModelAPI_Result> aRes = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
           if (aRes.get()) {
             aRes->setIsConcealed(true); // set concealed
             return;
@@ -638,15 +635,34 @@ void Model_Data::referencesToObjects(
       }
     } else if (aType == ModelAPI_AttributeRefList::typeId()) { // list of references
       aReferenced = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(anAttr)->list();
-    } else if (aType == ModelAPI_AttributeSelection::typeId()) { // selection attribute
+    }
+    else if (aType == ModelAPI_AttributeSelection::typeId()) { // selection attribute
       std::shared_ptr<ModelAPI_AttributeSelection> aRef = std::dynamic_pointer_cast<
-          ModelAPI_AttributeSelection>(anAttr);
-      aReferenced.push_back(aRef->context());
+        ModelAPI_AttributeSelection>(anAttr);
+      FeaturePtr aRefFeat = aRef->contextFeature();
+      if (aRefFeat.get()) { // reference to all results of the referenced feature
+        const std::list<ResultPtr>& allRes = aRefFeat->results();
+        std::list<ResultPtr>::const_iterator aRefRes = allRes.cbegin();
+        for(; aRefRes != allRes.cend(); aRefRes++) {
+          aReferenced.push_back(*aRefRes);
+        }
+      } else {
+        aReferenced.push_back(aRef->context());
+      }
     } else if (aType == ModelAPI_AttributeSelectionList::typeId()) { // list of selection attributes
       std::shared_ptr<ModelAPI_AttributeSelectionList> aRef = std::dynamic_pointer_cast<
           ModelAPI_AttributeSelectionList>(anAttr);
       for(int a = 0, aSize = aRef->size(); a < aSize; ++a) {
-        aReferenced.push_back(aRef->value(a)->context());
+        FeaturePtr aRefFeat = aRef->value(a)->contextFeature();
+        if (aRefFeat.get()) { // reference to all results of the referenced feature
+          const std::list<ResultPtr>& allRes = aRefFeat->results();
+          std::list<ResultPtr>::const_iterator aRefRes = allRes.cbegin();
+          for (; aRefRes != allRes.cend(); aRefRes++) {
+            aReferenced.push_back(*aRefRes);
+          }
+        } else {
+          aReferenced.push_back(aRef->value(a)->context());
+        }
       }
     } else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
       std::shared_ptr<ModelAPI_AttributeRefAttrList> aRefAttr = std::dynamic_pointer_cast<
index ae27c2af263a9105cc5e04dfca96e5f0b7994a5c..caba9de1337b13ec201b8b6032512169212f07d7 100755 (executable)
@@ -30,7 +30,6 @@
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <Events_Loop.h>
 #include <Events_InfoMessage.h>
 
@@ -1055,6 +1054,14 @@ int Model_Document::size(const std::string& theGroupID, const bool theAllowFolde
   return myObjs->size(theGroupID, theAllowFolder);
 }
 
+std::shared_ptr<ModelAPI_Object> Model_Document::parent(
+  const std::shared_ptr<ModelAPI_Object> theChild)
+{
+  if(myObjs == 0) // may be on close
+    return ObjectPtr();
+  return myObjs->parent(theChild);
+}
+
 std::shared_ptr<ModelAPI_Feature> Model_Document::currentFeature(const bool theVisible)
 {
   if (!myObjs) // on close document feature destruction it may call this method
@@ -1567,21 +1574,11 @@ void Model_Document::setActive(const bool theFlag)
       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(
         object(ModelAPI_Feature::group(), a));
       if (aFeature.get() && aFeature->data()->isValid()) {
-        const std::list<std::shared_ptr<ModelAPI_Result> >& aResList = aFeature->results();
-        std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResList.begin();
-        for(; aRes != aResList.end(); aRes++) {
+        std::list<ResultPtr> aResults;
+        ModelAPI_Tools::allResults(aFeature, aResults);
+        for (std::list<ResultPtr>::iterator aRes = aResults.begin();
+                                                aRes != aResults.end(); aRes++) {
           ModelAPI_EventCreator::get()->sendUpdated(*aRes, aRedispEvent);
-          // #issue 1048: sub-compsolids also
-          ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aRes);
-          if (aCompRes.get()) {
-            int aNumSubs = aCompRes->numberOfSubs();
-            for(int a = 0; a < aNumSubs; a++) {
-              ResultPtr aSub = aCompRes->subResult(a);
-              if (aSub.get()) {
-                ModelAPI_EventCreator::get()->sendUpdated(aSub, aRedispEvent);
-              }
-            }
-          }
         }
       }
     }
@@ -1755,9 +1752,15 @@ std::shared_ptr<ModelAPI_Feature> Model_Document::producedByFeature(
   if (aShape.IsNull())
     return FeaturePtr();
 
-  // for comsolids and compounds all the naming is located in the main object, so, try to use
+  // for compsolids and compounds all the naming is located in the main object, so, try to use
   // it first
-  ResultCompSolidPtr aMain = ModelAPI_Tools::compSolidOwner(theResult);
+  ResultBodyPtr aMain = ModelAPI_Tools::bodyOwner(theResult);
+  while (aMain.get()) { // get the top-most main
+    ResultBodyPtr aNextMain = ModelAPI_Tools::bodyOwner(aMain);
+    if (aNextMain.get())
+      aMain = aNextMain;
+    else break;
+  }
   if (aMain.get()) {
     FeaturePtr aMainRes = producedByFeature(aMain, theShape);
     if (aMainRes)
index 0f6b32ed6e8093863a453ecf130ee42d200155d7..98c44ea64b94944a02f6559399926036b3305220 100644 (file)
@@ -149,6 +149,11 @@ class Model_Document : public ModelAPI_Document
   //! \param theAllowFolder take into account grouping feature by folders
   MODEL_EXPORT virtual int size(const std::string& theGroupID, const bool theAllowFolder = false);
 
+  //! Returns the parent object of this child. This may be result or feature, parent of a
+  //! top result. Fast method, that uses internal data structure specifics.
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Object> parent(
+    const std::shared_ptr<ModelAPI_Object> theChild);
+
   //! Returns the feature that is currently edited in this document, normally
   //! this is the latest created feature
   //! \param theVisible use visible features only: flag is true for Object Browser functionality
@@ -383,7 +388,7 @@ class Model_Document : public ModelAPI_Document
   friend class Model_AttributeRefAttrList;
   friend class Model_AttributeSelection;
   friend class Model_ResultPart;
-  friend class Model_ResultCompSolid;
+  friend class Model_ResultBody;
   friend class Model_ResultConstruction;
   friend class Model_SelectionNaming;
   friend class DFBrowser;
index 30d6e70a4321301f96d804b55120fcf018f7909d..e113d3ae7f73b1cbcd66bce97a8dc37b41ff8172 100644 (file)
@@ -88,16 +88,18 @@ void Model_ObjectUpdatedMessage::Join(const std::shared_ptr<Events_MessageGroup>
 /////////////////////// DELETED MESSAGE /////////////////////////////
 Model_ObjectDeletedMessage::Model_ObjectDeletedMessage(
     const std::shared_ptr<ModelAPI_Document>& theDoc, const std::string& theGroup)
-    : ModelAPI_ObjectDeletedMessage(messageId(), 0),
-      myDoc(theDoc)
+    : ModelAPI_ObjectDeletedMessage(messageId(), 0)
 {
-  if (!theGroup.empty())
-    myGroups.insert(theGroup);
+  if (!theGroup.empty()) {
+    myGroups.push_back(
+      std::pair<std::shared_ptr<ModelAPI_Document>, std::string>(theDoc, theGroup));
+  }
 }
 
 std::shared_ptr<Events_MessageGroup> Model_ObjectDeletedMessage::newEmpty()
 {
-  return std::shared_ptr<Model_ObjectDeletedMessage>(new Model_ObjectDeletedMessage(myDoc, ""));
+  static const std::shared_ptr<ModelAPI_Document> anEmpty;
+  return std::shared_ptr<Model_ObjectDeletedMessage>(new Model_ObjectDeletedMessage(anEmpty, ""));
 }
 
 const Events_ID Model_ObjectDeletedMessage::messageId()
@@ -110,9 +112,19 @@ void Model_ObjectDeletedMessage::Join(const std::shared_ptr<Events_MessageGroup>
 {
   std::shared_ptr<Model_ObjectDeletedMessage> aJoined =
     std::dynamic_pointer_cast<Model_ObjectDeletedMessage>(theJoined);
-  std::set<std::string>::iterator aGIter = aJoined->myGroups.begin();
-  for (; aGIter != aJoined->myGroups.end(); aGIter++) {
-    myGroups.insert(*aGIter);
+
+  const std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>& aJGroups =
+    aJoined->groups();
+
+  std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>::iterator aGIter;
+  std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>::const_iterator aJIter;
+  for (aJIter = aJGroups.cbegin(); aJIter != aJGroups.cend(); aJIter++) {
+    for (aGIter = myGroups.begin(); aGIter != myGroups.end(); aGIter++) {
+      if (aGIter->first == aJIter->first && aGIter->second == aJIter->second)
+        break; // exists, so no need to insert
+    }
+    if (aGIter == myGroups.end())
+      myGroups.push_back(*aJIter);
   }
 }
 
index c7a46b12027854aec49f74304c4ab1eca9fdac4b..c0ed012542e2d581b7ad723f2d70aa8ef789b500 100644 (file)
@@ -69,8 +69,8 @@ class Model_ObjectUpdatedMessage : public ModelAPI_ObjectUpdatedMessage
 /// Message that feature was deleted (used for Object Browser update)
 class Model_ObjectDeletedMessage : public ModelAPI_ObjectDeletedMessage
 {
-  std::shared_ptr<ModelAPI_Document> myDoc;  ///< document owner of the feature
-  std::set<std::string> myGroups;  ///< group identifiers that contained the deleted feature
+  ///< group identifiers that contained the deleted feature and document where they are deleted
+  std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string> > myGroups;
 
   /// Use ModelAPI for creation of this event.
   Model_ObjectDeletedMessage(const std::shared_ptr<ModelAPI_Document>& theDoc,
@@ -78,14 +78,9 @@ class Model_ObjectDeletedMessage : public ModelAPI_ObjectDeletedMessage
 
   friend class Model_EventCreator;
  public:
-  /// Returns the document that has been updated
-  virtual std::shared_ptr<ModelAPI_Document> document() const
-  {
-    return myDoc;
-  }
-
   /// Returns the group where the objects were deleted
-  virtual const std::set<std::string>& groups() const
+  virtual const std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string> >&
+    groups() const
   {
     return myGroups;
   }
index b4e516cd64e75305d523ad0c750635d14376c1f0..4c44977c41b3d8f083148b17bb27b4a59bd204a7 100644 (file)
@@ -26,7 +26,6 @@
 #include <Model_ResultPart.h>
 #include <Model_ResultConstruction.h>
 #include <Model_ResultBody.h>
-#include <Model_ResultCompSolid.h>
 #include <Model_ResultGroup.h>
 #include <Model_ResultField.h>
 #include <Model_ResultParameter.h>
@@ -556,41 +555,53 @@ ObjectPtr Model_Objects::object(TDF_Label theLabel)
   FeaturePtr aFeature = feature(theLabel);
   if (aFeature.get())
     return feature(theLabel);
-  TDF_Label aFeatureLabel = theLabel.Father().Father();  // let's suppose it is result
-  aFeature = feature(aFeatureLabel);
-  bool isSubResult = false;
-  if (!aFeature.get() && aFeatureLabel.Depth() > 1) { // let's suppose this is sub-result of result
+  TDF_Label aFeatureLabel = theLabel;  // let's suppose it is result of this feature
+  TDF_LabelList aSubLabs; // sub - labels from higher level to lower level of result
+  while(!aFeature.get() && aFeatureLabel.Depth() > 1) {
+    aSubLabs.Prepend(aFeatureLabel);
     aFeatureLabel = aFeatureLabel.Father().Father();
     aFeature = feature(aFeatureLabel);
-    isSubResult = true;
   }
   if (aFeature.get()) {
-    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
-    for (; aRIter != aResults.cend(); aRIter++) {
-      if (isSubResult) {
-        ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aRIter);
-        if (aCompRes.get()) {
-          int aNumSubs = aCompRes->numberOfSubs();
-          for(int a = 0; a < aNumSubs; a++) {
-            ResultPtr aSub = aCompRes->subResult(a);
-            if (aSub.get()) {
-              std::shared_ptr<Model_Data> aSubData = std::dynamic_pointer_cast<Model_Data>(
-                  aSub->data());
-              if (aSubData->label().Father().IsEqual(theLabel))
-                return aSub;
+    ResultPtr aCurrentResult;
+    // searching for results then sub-results label by label
+    for(TDF_ListIteratorOfLabelList aSubLab(aSubLabs); aSubLab.More(); aSubLab.Next()) {
+      if (aCurrentResult.get()) { // iterate sub-results of result
+        ResultBodyPtr anOwner = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aCurrentResult);
+        if (!anOwner)
+          return ObjectPtr(); // only Body can have sub-results
+        int a, aNumSubs = anOwner->numberOfSubs();
+        for(a = 0; a < aNumSubs; a++) {
+          ResultPtr aSub = anOwner->subResult(a);
+          if (aSub.get()) {
+            std::shared_ptr<Model_Data> aSubData = std::dynamic_pointer_cast<Model_Data>(
+              aSub->data());
+            const TDF_Label& aSubLabVal = aSubLab.ChangeValue();
+            if (aSubData->label().Father().IsEqual(aSubLabVal)) {
+              aCurrentResult = aSub;
+              break;
             }
           }
         }
-      } else {
-        std::shared_ptr<Model_Data> aResData = std::dynamic_pointer_cast<Model_Data>(
-            (*aRIter)->data());
-        if (aResData->label().Father().IsEqual(theLabel))
-          return *aRIter;
+        if (a == aNumSubs) // not found an appropriate sub-result of result
+          return ObjectPtr();
+      } else { // iterate results of feature
+        const std::list<ResultPtr>& aResults = aFeature->results();
+        std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
+        for(; aRIter != aResults.cend(); aRIter++) {
+          std::shared_ptr<Model_Data> aResData = std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
+          if (aResData->label().Father().IsEqual(aSubLab.ChangeValue())) {
+            aCurrentResult = *aRIter;
+            break;
+          }
+        }
+        if (aRIter == aResults.cend()) // not found an appropriate result of feature
+          return ObjectPtr();
       }
     }
+    return aCurrentResult;
   }
-  return FeaturePtr();  // not found
+  return ObjectPtr();  // not found
 }
 
 ObjectPtr Model_Objects::object(const std::string& theGroupID,
@@ -622,24 +633,12 @@ std::shared_ptr<ModelAPI_Object> Model_Objects::objectByName(
     std::list<std::shared_ptr<ModelAPI_Feature> > allObjs = allFeatures();
     std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anObjIter = allObjs.begin();
     for(; anObjIter != allObjs.end(); anObjIter++) {
-      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = (*anObjIter)->results();
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
-      for (; aRIter != aResults.cend(); aRIter++) {
-        if (aRIter->get() && (*aRIter)->groupName() == theGroupID) {
-          if ((*aRIter)->data()->name() == theName)
-            return *aRIter;
-          ResultCompSolidPtr aCompRes =
-            std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aRIter);
-          if (aCompRes.get()) {
-            int aNumSubs = aCompRes->numberOfSubs();
-            for(int a = 0; a < aNumSubs; a++) {
-              ResultPtr aSub = aCompRes->subResult(a);
-              if (aSub.get() && aSub->groupName() == theGroupID) {
-                if (aSub->data()->name() == theName)
-                  return aSub;
-              }
-            }
-          }
+      std::list<ResultPtr> allRes;
+      ModelAPI_Tools::allResults(*anObjIter, allRes);
+      for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+        if (aRes->get() && (*aRes)->groupName() == theGroupID) {
+          if ((*aRes)->data()->name() == theName)
+            return *aRes;
         }
       }
     }
@@ -678,6 +677,21 @@ int Model_Objects::size(const std::string& theGroupID, const bool theAllowFolder
   return aGroupID.empty() ? int(myHistory[theGroupID].size()) : int(myHistory[aGroupID].size());
 }
 
+std::shared_ptr<ModelAPI_Object> Model_Objects::parent(
+  const std::shared_ptr<ModelAPI_Object> theChild)
+{
+  if (theChild.get()) {
+    std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theChild->data());
+    TDF_Label aLab = aData->label();
+    if (!aLab.IsNull() && aLab.Depth() > 2) {
+      ObjectPtr anObj = object(aLab.Father().Father().Father());
+      return anObj;
+    }
+  }
+  return ObjectPtr();
+}
+
+
 void Model_Objects::allResults(const std::string& theGroupID, std::list<ResultPtr>& theResults)
 {
   // iterate the array of references and get feature by feature from the array
@@ -1166,10 +1180,10 @@ bool Model_Objects::hasCustomName(DataPtr theFeatureData,
                                   int theResultIndex,
                                   std::string& theParentName) const
 {
-  ResultCompSolidPtr aCompSolidRes =
-      std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theFeatureData->owner());
-  if (aCompSolidRes) {
-    FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner());
+  ResultBodyPtr aBodyRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theFeatureData->owner());
+  if (aBodyRes && std::dynamic_pointer_cast<Model_Data>(theFeatureData)->label().Depth() < 7) {
+    // only for top-results (works for the cases when results are not yet added to the feature)
+    FeaturePtr anOwner = ModelAPI_Feature::feature(theResult);
 
     // names of sub-solids in CompSolid should be default (for example,
     // result of boolean operation 'Boolean_1' is a CompSolid which is renamed to 'MyBOOL',
@@ -1177,18 +1191,18 @@ bool Model_Objects::hasCustomName(DataPtr theFeatureData,
     std::ostringstream aDefaultName;
     aDefaultName << anOwner->name();
     // compute default name of CompSolid (name of feature + index of CompSolid's result)
-    int aCompSolidResultIndex = 0;
+    int aBodyResultIndex = 0;
     const std::list<ResultPtr>& aResults = anOwner->results();
-    for (std::list<ResultPtr>::const_iterator anIt = aResults.begin();
-         anIt != aResults.end(); ++anIt, ++aCompSolidResultIndex)
-      if (aCompSolidRes == *anIt)
+    std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+    for(; anIt != aResults.end(); ++anIt, ++aBodyResultIndex)
+      if(aBodyRes == *anIt)
         break;
-    aDefaultName << "_" << (aCompSolidResultIndex + 1);
+    aDefaultName << "_" << (aBodyResultIndex + 1);
     theParentName = aDefaultName.str();
     return false;
   }
 
-  std::pair<std::string, bool> aName = ModelAPI_Tools::getDefaultName(theResult, theResultIndex);
+  std::pair<std::string, bool> aName = ModelAPI_Tools::getDefaultName(theResult);
   if (aName.second)
     theParentName = aName.first;
   return aName.second;
@@ -1242,27 +1256,14 @@ std::shared_ptr<ModelAPI_ResultBody> Model_Objects::createBody(
     const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
 {
   TDF_Label aLab = resultLabel(theFeatureData, theIndex);
-  // for feature create compsolid, but for result sub create body:
-  // only one level of recursion is supported now
-  ResultPtr aResultOwner = std::dynamic_pointer_cast<ModelAPI_Result>(theFeatureData->owner());
-  ObjectPtr anOldObject;
-  if (aResultOwner.get()) {
-    TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str());
-  } else { // in compsolid (higher level result) old object probably may be found
-    TDataStd_Comment::Set(aLab, ModelAPI_ResultCompSolid::group().c_str());
-    anOldObject = object(aLab);
-  }
+  TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str());
+  ObjectPtr anOldObject = object(aLab);
   std::shared_ptr<ModelAPI_ResultBody> aResult;
   if (anOldObject.get()) {
     aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anOldObject);
   }
   if (!aResult.get()) {
-    // create compsolid anyway; if it is compsolid, it will create sub-bodies internally
-    if (aResultOwner.get()) {
-      aResult = std::shared_ptr<ModelAPI_ResultBody>(new Model_ResultBody);
-    } else {
-      aResult = std::shared_ptr<ModelAPI_ResultBody>(new Model_ResultCompSolid);
-    }
+    aResult = std::shared_ptr<ModelAPI_ResultBody>(new Model_ResultBody);
     storeResult(theFeatureData, aResult, theIndex);
   }
   return aResult;
@@ -1790,7 +1791,7 @@ std::shared_ptr<ModelAPI_Feature> Model_Objects::feature(
   if (aData.get()) {
     TDF_Label aFeatureLab = aData->label().Father().Father().Father();
     FeaturePtr aFeature = feature(aFeatureLab);
-    if (!aFeature.get() && aFeatureLab.Depth() > 1) { // this may be sub-result of result
+    while(!aFeature.get() && aFeatureLab.Depth() > 1) { // this may be sub-result of result
       aFeatureLab = aFeatureLab.Father().Father();
       aFeature = feature(aFeatureLab);
     }
@@ -1863,8 +1864,7 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set<FeaturePtr>& t
       TDF_Label anArgLab = aLabIter.Value();
       Handle(TDataStd_Comment) aGroup;
       if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) {
-        if (aGroup->Get() == ModelAPI_ResultBody::group().c_str() ||
-            aGroup->Get() == ModelAPI_ResultCompSolid::group().c_str()) {
+        if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
           aNewBody = createBody(theFeature->data(), aResIndex);
         } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
           std::shared_ptr<ModelAPI_ResultPart> aNewP = createPart(theFeature->data(), aResIndex);
index d6f3d383f741867d3258b2947d2011fa034f2052..0991cf21077dba0fe2b3bcc38a0caafd91f4ebbf 100644 (file)
@@ -109,6 +109,10 @@ class Model_Objects
   //! \param theAllowFolder take into account grouping feature by folders
   int size(const std::string& theGroupID, const bool theAllowFolder = false);
 
+  //! Returns the parent object of this child. This may be result or feature, parent of a
+  //! top result. Fast method, that uses internal data structure specifics.
+  std::shared_ptr<ModelAPI_Object> parent(const std::shared_ptr<ModelAPI_Object> theChild);
+
   //! Returns all (and disabled) results of the given type.
   //! Not fast method (iterates all features).
   void allResults(const std::string& theGroupID, std::list<ResultPtr>& theResults);
index 731a520de0bb6fcff6f1d14a725b60612737cb04..e168c6c1a0f96cb09234afe9bc6fa4aeeb2848b5 100644 (file)
 //
 
 #include <Model_ResultBody.h>
+
+#include <Model_Document.h>
+#include <Model_Objects.h>
 #include <Model_BodyBuilder.h>
-#include <ModelAPI_ResultCompSolid.h>
-#include <ModelAPI_Tools.h>
-#include <Config_PropManager.h>
+#include <Model_Document.h>
+#include <ModelAPI_Object.h>
 #include <ModelAPI_Events.h>
-// DEB
-//#include <TCollection_AsciiString.hxx>
-//#include <TDF_Tool.hxx>
-//#define DEB_IMPORT 1
+#include <ModelAPI_Tools.h>
+#include <Events_Loop.h>
+
+#include <TopoDS_Shape.hxx>
+#include <TopExp_Explorer.hxx>
 
-Model_ResultBody::Model_ResultBody()
+
+Model_ResultBody::Model_ResultBody() : ModelAPI_ResultBody()
 {
   myBuilder = new Model_BodyBuilder(this);
-  myWasConcealed = false;
-  myConnect = ConnectionNotComputed;
+  myLastConcealed = false;
+  updateSubs(shape()); // in case of open, etc.
+}
+
+Model_ResultBody::~Model_ResultBody()
+{
+  updateSubs(std::shared_ptr<GeomAPI_Shape>()); // erase sub-results
+  delete myBuilder;
+}
+
+void Model_ResultBody::loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS,
+    std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
+    const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
+    const bool theIsStoreSeparate,
+    const bool theIsStoreAsGenerated,
+    const bool theSplitInSubs)
+{
+  if (theSplitInSubs && mySubs.size()) { // consists of subs
+    std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
+    for(; aSubIter != mySubs.cend(); aSubIter++) {
+      // check that sub-shape was also created as modification of ShapeIn
+      /* to find when it is needed later to enable: to store modification of sub-bodies not only as primitives
+      GeomShapePtr aSubGeomShape = (*aSubIter)->shape();
+      if (!theIsStoreAsGenerated && aSubGeomShape.get() && !aSubGeomShape->isNull()) {
+        TopoDS_Shape aSubShape = aSubGeomShape->impl<TopoDS_Shape>();
+        TopoDS_Shape aWholeIn = theShapeIn->impl<TopoDS_Shape>();
+        for(TopExp_Explorer anExp(aWholeIn, aSubShape.ShapeType()); anExp.More(); anExp.Next()) {
+          ListOfShape aHistory;
+          std::shared_ptr<GeomAPI_Shape> aSubIn(new GeomAPI_Shape());
+          aSubIn->setImpl((new TopoDS_Shape(anExp.Current())));
+          theMS->modified(aSubIn, aHistory);
+          std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = aHistory.begin();
+          for (; anIt != aHistory.end(); anIt++) {
+            if ((*anIt)->isSame(aSubGeomShape)) {
+              (*aSubIter)->storeModified(aSubIn, aSubGeomShape, -2); // -2 is to avoid clearing
+            }
+          }
+        }
+      }*/
+      (*aSubIter)->loadAndOrientModifiedShapes(
+        theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
+        theIsStoreAsGenerated, theSplitInSubs);
+    }
+  } else { // do for this directly
+    myBuilder->loadAndOrientModifiedShapes(
+      theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
+        theIsStoreAsGenerated);
+  }
+}
+
+int Model_ResultBody::numberOfSubs(bool forTree) const
+{
+  return int(mySubs.size());
+}
+
+ResultBodyPtr Model_ResultBody::subResult(const int theIndex, bool forTree) const
+{
+  return mySubs.at(theIndex);
+}
+
+bool Model_ResultBody::isSub(ObjectPtr theObject, int& theIndex) const
+{
+  std::map<ObjectPtr, int>::const_iterator aFound = mySubsMap.find(theObject);
+  if (aFound != mySubsMap.end()) {
+    theIndex = aFound->second;
+    return true;
+  }
+  return false;
 }
 
 void Model_ResultBody::colorConfigInfo(std::string& theSection, std::string& theName,
@@ -47,45 +117,151 @@ void Model_ResultBody::colorConfigInfo(std::string& theSection, std::string& the
 bool Model_ResultBody::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
 {
   bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag);
-  if (aChanged && data()->isValid()) { // state is changed, so modifications are needed
+  if (aChanged) { // state is changed, so modifications are needed
     myBuilder->evolutionToSelection(theFlag);
+    updateSubs(shape()); // to set disabled/enabled
   }
   return aChanged;
 }
 
-bool Model_ResultBody::isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape)
+bool Model_ResultBody::isConcealed()
 {
-  return myBuilder->isLatestEqual(theShape);
+  return myLastConcealed;
 }
 
-bool Model_ResultBody::isConcealed()
+void Model_ResultBody::setIsConcealed(const bool theValue)
 {
-  bool aResult = false;
-  if (ModelAPI_ResultBody::isConcealed()) {
-    aResult = true;
-  } else {
-    ResultPtr aThis = std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner());
-    if (aThis.get()) {
-      ResultCompSolidPtr aParent = ModelAPI_Tools::compSolidOwner(aThis);
-      if (aParent.get()) {
-        if (aParent->isConcealed())
-          aResult = true;
+  if (ModelAPI_ResultBody::isConcealed() != theValue) {
+    ModelAPI_ResultBody::setIsConcealed(theValue);
+    updateConcealment();
+  }
+}
+
+// recursively check all subs for concealment flag, returns true if everybody have "flag" state,
+// in theAll returns results with "flag" state
+static bool checkAllSubs(ResultBodyPtr theParent, bool theFlag, std::list<ResultBodyPtr>& theAll)
+{
+  if (theParent->isConcealed() != theFlag)
+    theAll.push_back(theParent);
+  bool aResult = theParent->ModelAPI_ResultBody::isConcealed() == theFlag;
+  for(int a = 0; a < theParent->numberOfSubs(); a++) {
+    bool aSubRes = checkAllSubs(theParent->subResult(a), theFlag, theAll);
+    if (theFlag)
+      aResult = aResult || aSubRes; // concealed: one makes concealed everyone
+    else
+      aResult = aResult && aSubRes; // not concealed: all must be not concealed
+  }
+  return aResult;
+}
+
+void Model_ResultBody::updateConcealment()
+{
+  if (myLastConcealed != ModelAPI_ResultBody::isConcealed()) {
+    // check the whole tree of results: if one is concealed, everybody are concealed
+    ResultBodyPtr anOwner = std::dynamic_pointer_cast<ModelAPI_ResultBody>(data()->owner());
+    ResultBodyPtr aParent = ModelAPI_Tools::bodyOwner(anOwner);
+    while(aParent.get()) {
+      anOwner = aParent;
+      aParent = ModelAPI_Tools::bodyOwner(anOwner);
+    }
+    // iterate all results and collect all results whose state may be updated
+    std::list<ResultBodyPtr> anUpdated;
+    bool aNewFlag = !myLastConcealed;
+    if (checkAllSubs(anOwner, aNewFlag, anUpdated)) { // state of everyone must be updated
+      std::list<ResultBodyPtr>::iterator aRes = anUpdated.begin();
+      for(; aRes != anUpdated.end(); aRes++) {
+        bool aLastConcealed = (*aRes)->isConcealed();
+        if (aNewFlag != aLastConcealed) {
+          std::dynamic_pointer_cast<Model_ResultBody>(*aRes)->myLastConcealed = aNewFlag;
+          if (aNewFlag) { // become concealed, behaves like removed
+            ModelAPI_EventCreator::get()->sendDeleted(document(), groupName());
+          } else { // become not-concealed, behaves like created
+            static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+            ModelAPI_EventCreator::get()->sendUpdated(*aRes, anEvent);
+          }
+          static Events_ID EVENT_DISP = // must be redisplayed in any case
+            Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+          ModelAPI_EventCreator::get()->sendUpdated(*aRes, EVENT_DISP);
+        }
       }
     }
   }
-  if (myWasConcealed != aResult) {
-    myWasConcealed = aResult;
-    if (aResult) { // hidden unit must be redisplayed (hidden)
-      ModelAPI_EventCreator::get()->sendDeleted(document(), this->groupName());
-      // redisplay for the viewer (it must be disappeared also)
-      static Events_ID EVENT_DISP =
-        Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-      ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), EVENT_DISP);
-    } else { // was not concealed become concealed => delete event
-      static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-      ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), anEvent);
+}
+
+void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisShape)
+{
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static Events_ID EVENT_UPD = aLoop->eventByName(EVENT_OBJECT_UPDATED);
+  static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+  // iterate all sub-solids of compsolid to make sub-results synchronized with them
+  TopoDS_Shape aThisShape;
+  if (theThisShape.get()) aThisShape = theThisShape->impl<TopoDS_Shape>();
+  if (!aThisShape.IsNull() && (aThisShape.ShapeType() == TopAbs_COMPSOLID ||
+       aThisShape.ShapeType() == TopAbs_COMPOUND)) {
+    bool aWasEmpty = mySubs.empty();
+    Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
+    unsigned int aSubIndex = 0;
+    TopoDS_Iterator aShapesIter(aThisShape);
+    for(; aShapesIter.More(); aShapesIter.Next(), aSubIndex++) {
+      std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
+      aShape->setImpl(new TopoDS_Shape(aShapesIter.Value()));
+      ResultBodyPtr aSub;
+      if (mySubs.size() <= aSubIndex) { // it is needed to create a new sub-result
+        aSub = anObjects->createBody(this->data(), aSubIndex);
+        mySubs.push_back(aSub);
+        mySubsMap[aSub] = int(mySubs.size() - 1);
+      } else { // just update shape of this result
+        aSub = mySubs[aSubIndex];
+      }
+      if (!aShape->isEqual(aSub->shape())) {
+        aSub->store(aShape, false);
+        aECreator->sendUpdated(aSub, EVENT_DISP);
+        aECreator->sendUpdated(aSub, EVENT_UPD);
+      }
+      aSub->setDisabled(aSub, isDisabled());
+    }
+    // erase left, unused results
+    while(mySubs.size() > aSubIndex) {
+      ResultBodyPtr anErased = *(mySubs.rbegin());
+      if (anErased->ModelAPI_ResultBody::isConcealed()) {
+        anErased->ModelAPI_ResultBody::setIsConcealed(false);
+        std::dynamic_pointer_cast<Model_ResultBody>(anErased)->updateConcealment();
+      }
+      anErased->setDisabled(anErased, true);
+      mySubsMap.erase(anErased);
+      mySubs.pop_back();
+    }
+    if (aWasEmpty) { // erase all subs
+      // redisplay this because result with and without subs are displayed differently
+      aECreator->sendUpdated(data()->owner(), EVENT_DISP);
+    }
+  } else if (!mySubs.empty()) { // erase all subs
+    while(!mySubs.empty()) {
+      ResultBodyPtr anErased = *(mySubs.rbegin());
+      if (anErased->ModelAPI_ResultBody::isConcealed()) {
+        anErased->ModelAPI_ResultBody::setIsConcealed(false);
+        std::dynamic_pointer_cast<Model_ResultBody>(anErased)->updateConcealment();
+      }
+      anErased->setDisabled(anErased, true); // even if it is invalid (to erase subs on abort/undo)
+      mySubs.pop_back();
     }
+    mySubsMap.clear();
+    // redisplay this because result with and without subs are displayed differently
+    aECreator->sendUpdated(data()->owner(), EVENT_DISP);
   }
+}
 
-  return aResult;
+bool Model_ResultBody::isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape)
+{
+  if (myBuilder->isLatestEqual(theShape))
+    return true;
+  // also check that it is asked for sub-elements
+  std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
+  for(; aSubIter != mySubs.cend(); aSubIter++) {
+    if (aSubIter->get() && (*aSubIter)->isLatestEqual(theShape)) {
+      return true;
+    }
+  }
+  return false;
 }
index 02f55cbdc99b08bee68a3e3f65139c64af2a377e..ad5f1c53136a25ca5a985f834ea5e400823a229f 100644 (file)
 
 #include "Model.h"
 #include <ModelAPI_ResultBody.h>
-//#include <GeomAlgoAPI_MakeShape.h>
-//#include <GeomAPI_DataMapOfShapeShape.h>
-//#include <vector>
-
-//class TNaming_Builder;
+#include <vector>
+#include <map>
 
 /**\class Model_ResultBody
- * \ingroup DataModel
- * \brief The body (shape) result of a feature.
- *
- * Provides a shape that may be displayed in the viewer.
- * May provide really huge results, so, working with this kind
- * of result must be optimized.
- */
+* \ingroup DataModel
+* \brief The body (shape) result of a feature.
+*
+* Provides a shape that may be displayed in the viewer.
+* May provide really huge results, so, working with this kind
+* of result must be optimized.
+* Also provides a conainer of sub-body result in case it is compound or compsolid.
+*/
 class Model_ResultBody : public ModelAPI_ResultBody
 {
-  /// builders that tores the naming history: one per label to allow store several shapes to one
-  /// label; index in vector corresponds to the label tag
-  //std::vector<TNaming_Builder*> myBuilders;
-
-  /// Flag that stores the previous state of "concealed": if it is changed,
-  /// The event is used to redisplay the body.
-  bool myWasConcealed;
+  /// Sub-bodies if this is compsolid or compound: zero-based index to subs
+  std::vector<ResultBodyPtr> mySubs;
+  /// Also keep map of result to index in mySubs to facilitate speed of access from OB
+  std::map<ObjectPtr, int> mySubsMap;
+  /// Keeps the last state of the concealment flag in order to update it when needed.
+  bool myLastConcealed;
 
 public:
+
+  /// Removes the stored builders
+  MODEL_EXPORT virtual ~Model_ResultBody();
+
+  /// load and orient modified shapes for sub-objects
+  MODEL_EXPORT virtual void loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* theMS,
+    std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
+    const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
+    const bool theIsStoreSeparate = false, const bool theIsStoreAsGenerated = false,
+    const bool theSplitInSubs = false);
+
+
+  /// Returns the number of sub-elements
+  MODEL_EXPORT virtual int numberOfSubs(bool forTree = false) const;
+
+  /// Returns the sub-result by zero-base index
+  MODEL_EXPORT virtual ResultBodyPtr subResult(const int theIndex,
+    bool forTree = false) const;
+
+  /// Returns true if feature or reuslt belong to this composite feature as subs
+  /// Returns theIndex - zero based index of sub if found
+  MODEL_EXPORT virtual bool isSub(ObjectPtr theObject, int& theIndex) const;
+
   /// Returns the parameters of color definition in the resources config manager
   MODEL_EXPORT virtual void colorConfigInfo(std::string& theSection, std::string& theName,
                                             std::string& theDefault);
 
   /// Disables the result body: keeps the resulting shape as selection, but erases the underlaying
-  /// naming data structure if theFlag if false. Or restores everything on theFlag is true.
+  /// naming data structure if theFlag if false. Or restores every  thing on theFlag is true.
   MODEL_EXPORT virtual bool setDisabled(std::shared_ptr<ModelAPI_Result> theThis,
     const bool theFlag);
 
-  /// The compsolid is concealed if at least one of the sub is concealed,
-  /// so, sub is Concealed if at least one sub is concealed
+  /// The compsolid is concealed if at least one of the sub is concealed
   MODEL_EXPORT virtual bool isConcealed();
 
+  /// Sets all subs as concealed in the data tree (referenced by other objects)
+  MODEL_EXPORT virtual void setIsConcealed(const bool theValue);
+
   /// Returns true if the latest modification of this body in the naming history
   // is equal to the given shape
   MODEL_EXPORT virtual bool isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape);
 
-  /// Removes the stored builders
-  MODEL_EXPORT virtual ~Model_ResultBody() {};
-
 protected:
   /// Makes a body on the given feature
   Model_ResultBody();
 
+  /// Updates the sub-bodies if shape of this object is composite-solid
+  void updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisShape);
+
+  // Checks the state of children and partents to send events of creation/erase when needed
+  void updateConcealment();
+
   friend class Model_Objects;
 };
 
diff --git a/src/Model/Model_ResultCompSolid.cpp b/src/Model/Model_ResultCompSolid.cpp
deleted file mode 100755 (executable)
index 8cde4b9..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-// 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 <Model_ResultCompSolid.h>
-
-#include <Model_Document.h>
-#include <Model_Objects.h>
-#include <Model_BodyBuilder.h>
-#include <Model_Document.h>
-#include <ModelAPI_Object.h>
-#include <ModelAPI_Events.h>
-#include <Events_Loop.h>
-
-#include <TopoDS_Shape.hxx>
-#include <TopExp_Explorer.hxx>
-
-
-Model_ResultCompSolid::Model_ResultCompSolid()
-{
-  myBuilder = new Model_BodyBuilder(this);
-  myLastConcealed = false;
-  updateSubs(shape()); // in case of open, etc.
-}
-
-Model_ResultCompSolid::~Model_ResultCompSolid()
-{
-  updateSubs(std::shared_ptr<GeomAPI_Shape>()); // erase sub-results
-}
-
-void Model_ResultCompSolid::store(const std::shared_ptr<GeomAPI_Shape>& theShape,
-                                  const bool theIsStoreSameShapes)
-{
-  ModelAPI_ResultCompSolid::store(theShape, theIsStoreSameShapes);
-  updateSubs(theShape);
-}
-
-void Model_ResultCompSolid::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& theFromShape,
-    const std::shared_ptr<GeomAPI_Shape>& theToShape)
-{
-  ModelAPI_ResultCompSolid::storeGenerated(theFromShape, theToShape);
-  updateSubs(theToShape);
-}
-
-void Model_ResultCompSolid::storeModified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
-    const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theDecomposeSolidsTag)
-{
-  ModelAPI_ResultCompSolid::storeModified(theOldShape, theNewShape, theDecomposeSolidsTag);
-  updateSubs(theNewShape);
-}
-
-void Model_ResultCompSolid::loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS,
-    std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
-    const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
-    const bool theIsStoreSeparate,
-    const bool theIsStoreAsGenerated,
-    const bool theSplitInSubs)
-{
-  if (theSplitInSubs && mySubs.size()) { // consists of subs
-    std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
-    for(; aSubIter != mySubs.cend(); aSubIter++) {
-      // check that sub-shape was also created as modification of ShapeIn
-      /* to find when it is needed later to enable: to store modification of sub-bodies not only as primitives
-      GeomShapePtr aSubGeomShape = (*aSubIter)->shape();
-      if (!theIsStoreAsGenerated && aSubGeomShape.get() && !aSubGeomShape->isNull()) {
-        TopoDS_Shape aSubShape = aSubGeomShape->impl<TopoDS_Shape>();
-        TopoDS_Shape aWholeIn = theShapeIn->impl<TopoDS_Shape>();
-        for(TopExp_Explorer anExp(aWholeIn, aSubShape.ShapeType()); anExp.More(); anExp.Next()) {
-          ListOfShape aHistory;
-          std::shared_ptr<GeomAPI_Shape> aSubIn(new GeomAPI_Shape());
-          aSubIn->setImpl((new TopoDS_Shape(anExp.Current())));
-          theMS->modified(aSubIn, aHistory);
-          std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = aHistory.begin();
-          for (; anIt != aHistory.end(); anIt++) {
-            if ((*anIt)->isSame(aSubGeomShape)) {
-              (*aSubIter)->storeModified(aSubIn, aSubGeomShape, -2); // -2 is to avoid clearing
-            }
-          }
-        }
-      }*/
-      (*aSubIter)->loadAndOrientModifiedShapes(
-        theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
-        theIsStoreAsGenerated);
-    }
-  } else { // do for this directly
-    ModelAPI_ResultCompSolid::loadAndOrientModifiedShapes(
-    theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
-    theIsStoreAsGenerated);
-  }
-}
-
-int Model_ResultCompSolid::numberOfSubs(bool forTree) const
-{
-  return int(mySubs.size());
-}
-
-std::shared_ptr<ModelAPI_ResultBody> Model_ResultCompSolid::subResult(const int theIndex,
-                                                                      bool forTree) const
-{
-  return mySubs.at(theIndex);
-}
-
-bool Model_ResultCompSolid::isSub(ObjectPtr theObject, int& theIndex) const
-{
-  std::map<ObjectPtr, int>::const_iterator aFound = mySubsMap.find(theObject);
-  if (aFound != mySubsMap.end()) {
-    theIndex = aFound->second;
-    return true;
-  }
-  return false;
-}
-
-void Model_ResultCompSolid::colorConfigInfo(std::string& theSection, std::string& theName,
-  std::string& theDefault)
-{
-  theSection = "Visualization";
-  theName = "result_body_color";
-  theDefault = DEFAULT_COLOR();
-}
-
-bool Model_ResultCompSolid::setDisabled(std::shared_ptr<ModelAPI_Result> theThis,
-                                        const bool theFlag)
-{
-  bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag);
-  if (aChanged) { // state is changed, so modifications are needed
-    myBuilder->evolutionToSelection(theFlag);
-    updateSubs(shape()); // to set disabled/enabled
-  }
-  return aChanged;
-}
-
-bool Model_ResultCompSolid::isConcealed()
-{
-  bool aResult = false;;
-  if (ModelAPI_ResultCompSolid::isConcealed()) {
-    aResult = true;
-  } else {
-    std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
-    for(; aSubIter != mySubs.cend(); aSubIter++) {
-      if ((*aSubIter)->ModelAPI_ResultBody::isConcealed()) {
-        aResult = true;
-        break;
-      }
-    }
-  }
-  if (myLastConcealed != aResult) {
-    myLastConcealed = aResult;
-    //setIsConcealed(aResult); // set for all subs the same result
-    std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
-    for(; aSubIter != mySubs.cend(); aSubIter++) { // update the visualization status of each sub
-      if ((*aSubIter)->ModelAPI_ResultBody::isConcealed() != aResult) {
-        if (aResult) { // hidden unit must be redisplayed (hidden)
-          ModelAPI_EventCreator::get()->sendDeleted(document(), (*aSubIter)->groupName());
-          // redisplay for the viewer (it must be disappeared also)
-          static Events_ID EVENT_DISP =
-            Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-          ModelAPI_EventCreator::get()->sendUpdated(*aSubIter, EVENT_DISP);
-        } else { // was not concealed become concealed => delete event
-          static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-          ModelAPI_EventCreator::get()->sendUpdated(*aSubIter, anEvent);
-        }
-      }
-    }
-    // update the display state of the subs: explicitly call Model_ResultBody::isConcealed
-    for(aSubIter = mySubs.cbegin(); aSubIter != mySubs.cend(); aSubIter++) {
-      (*aSubIter)->isConcealed();
-    }
-  }
-  return aResult;
-}
-
-void Model_ResultCompSolid::setIsConcealed(const bool theValue)
-{
-  if (theValue != ModelAPI_ResultCompSolid::isConcealed()) {
-    std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
-    for(; aSubIter != mySubs.cend(); aSubIter++) {
-      if ((*aSubIter)->ModelAPI_ResultBody::isConcealed() != theValue) {
-        if (theValue) { // hidden unit must be redisplayed (hidden)
-          ModelAPI_EventCreator::get()->sendDeleted(document(), (*aSubIter)->groupName());
-          // redisplay for the viewer (it must be disappeared also)
-          static Events_ID EVENT_DISP =
-            Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-          ModelAPI_EventCreator::get()->sendUpdated(*aSubIter, EVENT_DISP);
-        } else { // was not concealed become concealed => delete event
-          static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-          ModelAPI_EventCreator::get()->sendUpdated(*aSubIter, anEvent);
-        }
-      }
-    }
-    ModelAPI_ResultCompSolid::setIsConcealed(theValue);
-    // to set correct myLastConcealed
-    isConcealed();
-  }
-  //myLastConcealed = theValue;
-}
-
-void Model_ResultCompSolid::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisShape)
-{
-  static Events_Loop* aLoop = Events_Loop::loop();
-  static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-  static Events_ID EVENT_UPD = aLoop->eventByName(EVENT_OBJECT_UPDATED);
-  static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
-  // iterate all sub-solids of compsolid to make sub-results synchronized with them
-  TopoDS_Shape aThisShape;
-  if (theThisShape.get()) aThisShape = theThisShape->impl<TopoDS_Shape>();
-  if (!aThisShape.IsNull() && (aThisShape.ShapeType() == TopAbs_COMPSOLID ||
-       aThisShape.ShapeType() == TopAbs_COMPOUND)) {
-    bool aWasEmpty = mySubs.empty();
-    Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
-    unsigned int aSubIndex = 0;
-    TopoDS_Iterator aShapesIter(aThisShape);
-    for(; aShapesIter.More(); aShapesIter.Next(), aSubIndex++) {
-      std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
-      aShape->setImpl(new TopoDS_Shape(aShapesIter.Value()));
-      ResultBodyPtr aSub;
-      if (mySubs.size() <= aSubIndex) { // it is needed to create a new sub-result
-        aSub = anObjects->createBody(this->data(), aSubIndex);
-        mySubs.push_back(aSub);
-        mySubsMap[aSub] = int(mySubs.size() - 1);
-      } else { // just update shape of this result
-        aSub = mySubs[aSubIndex];
-      }
-      if (!aShape->isEqual(aSub->shape())) {
-        aSub->store(aShape, false);
-        aECreator->sendUpdated(aSub, EVENT_DISP);
-        aECreator->sendUpdated(aSub, EVENT_UPD);
-      }
-      aSub->setDisabled(aSub, isDisabled());
-      aSub->setIsConcealed(myLastConcealed);
-    }
-    // erase left, unused results
-    while(mySubs.size() > aSubIndex) {
-      ResultBodyPtr anErased = *(mySubs.rbegin());
-      anErased->setDisabled(anErased, true);
-      mySubsMap.erase(anErased);
-      mySubs.pop_back();
-    }
-    if (aWasEmpty) { // erase all subs
-      // redisplay this because result with and without subs are displayed differently
-      aECreator->sendUpdated(data()->owner(), EVENT_DISP);
-    }
-  } else if (!mySubs.empty()) { // erase all subs
-    while(!mySubs.empty()) {
-      ResultBodyPtr anErased = *(mySubs.rbegin());
-      anErased->setDisabled(anErased, true); // even if it is invalid (to erase subs on abort/undo)
-      mySubs.pop_back();
-    }
-    mySubsMap.clear();
-    // redisplay this because result with and without subs are displayed differently
-    aECreator->sendUpdated(data()->owner(), EVENT_DISP);
-  }
-}
-
-bool Model_ResultCompSolid::isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape)
-{
-  if (myBuilder->isLatestEqual(theShape))
-    return true;
-  // also check that it is asked for sub-elements
-  std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
-  for(; aSubIter != mySubs.cend(); aSubIter++) {
-    if (aSubIter->get() && (*aSubIter)->isLatestEqual(theShape)) {
-      return true;
-    }
-  }
-  return false;
-}
diff --git a/src/Model/Model_ResultCompSolid.h b/src/Model/Model_ResultCompSolid.h
deleted file mode 100755 (executable)
index c748aee..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// 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 Model_ResultCompSolid_H_
-#define Model_ResultCompSolid_H_
-
-#include "Model.h"
-#include <ModelAPI_ResultCompSolid.h>
-#include <vector>
-#include <map>
-
-/**\class Model_ResultCompSolid
-* \ingroup DataModel
-* \brief The compsolid (container of body results) result of a feature.
-*
-* Provides a container of shapes that may be displayed in the viewer.
-*/
-class Model_ResultCompSolid : public ModelAPI_ResultCompSolid
-{
-  /// Sub-bodies if this is compsolid: zero base index to subs
-  std::vector<std::shared_ptr<ModelAPI_ResultBody> > mySubs;
-  /// Also keep map of result to index in mySubs to facilitate speed of access from OB
-  std::map<ObjectPtr, int> mySubsMap;
-  /// Flag that stores the previous state of "concealed": if it is changed,
-  /// The event must be generated to redisplay this and all subs.
-  bool myLastConcealed;
-
-
-public:
-
-  /// Removes the stored builders
-  MODEL_EXPORT virtual ~Model_ResultCompSolid();
-
-  /// Stores the shape (called by the execution method). Creates sub-results for compsolid.
-  MODEL_EXPORT virtual void store(const std::shared_ptr<GeomAPI_Shape>& theShape,
-                                  const bool theIsStoreSameShapes = true);
-
-  /// Stores the generated shape.  Creates sub-results for compsolid.
-  MODEL_EXPORT virtual void storeGenerated(const std::shared_ptr<GeomAPI_Shape>& theFromShape,
-    const std::shared_ptr<GeomAPI_Shape>& theToShape);
-
-  /// Stores the modified shape.  Creates sub-results for compsolid.
-  MODEL_EXPORT virtual void storeModified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
-    const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theDecomposeSolidsTag = 0);
-
-  /// load and orient modified shapes for sub-objects
-  MODEL_EXPORT virtual void loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* theMS,
-    std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
-    const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
-    const bool theIsStoreSeparate = false,
-    const bool theIsStoreAsGenerated = false,
-    const bool theSplitInSubs = false);
-
-
-  /// Returns the number of sub-elements
-  MODEL_EXPORT virtual int numberOfSubs(bool forTree = false) const;
-
-  /// Returns the sub-result by zero-base index
-  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_ResultBody> subResult(const int theIndex,
-    bool forTree = false) const;
-
-  /// Returns true if feature or reuslt belong to this composite feature as subs
-  /// Returns theIndex - zero based index of sub if found
-  MODEL_EXPORT virtual bool isSub(ObjectPtr theObject, int& theIndex) const;
-
-  /// Returns the parameters of color definition in the resources config manager
-  MODEL_EXPORT virtual void colorConfigInfo(std::string& theSection, std::string& theName,
-                                            std::string& theDefault);
-
-  /// Disables the result body: keeps the resulting shape as selection, but erases the underlaying
-  /// naming data structure if theFlag if false. Or restores everything on theFlag is true.
-  MODEL_EXPORT virtual bool setDisabled(std::shared_ptr<ModelAPI_Result> theThis,
-    const bool theFlag);
-
-  /// The compsolid is concealed if at least one of the sub is concealed
-  MODEL_EXPORT virtual bool isConcealed();
-
-  /// Sets all subs as concealed in the data tree (referenced by other objects)
-  MODEL_EXPORT virtual void setIsConcealed(const bool theValue);
-
-  /// Returns true if the latest modification of this body in the naming history
-  // is equal to the given shape
-  MODEL_EXPORT virtual bool isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape);
-
-protected:
-  /// Makes a body on the given feature
-  Model_ResultCompSolid();
-
-  /// Updates the sub-bodies if shape of this object is composite-solid
-  void updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisShape);
-
-  friend class Model_Objects;
-};
-
-#endif
index be25462d976eb73e15897922f91a0b5c761da9d1..1b1c51e9ec70901a076e22a19d15503fb263dae5 100644 (file)
@@ -141,10 +141,10 @@ std::string Model_SelectionNaming::getShapeName(
             !aNS->Label().IsDescendant(aContextData->label())) {
           isNeedContextName = false;
           TDF_Label aNSDataLab = aNS->Label();
-          while(aNSDataLab.Depth() != 7 && aNSDataLab.Depth() > 5)
+          if (aNSDataLab.Depth() % 2 == 0)
             aNSDataLab = aNSDataLab.Father();
           ObjectPtr aNewContext = theDoc->objects()->object(aNSDataLab);
-          if (!aNewContext.get() && aNSDataLab.Depth() == 7) {
+          while(!aNewContext.get() && aNSDataLab.Depth() > 5) {
             aNSDataLab = aNSDataLab.Father().Father();
             aNewContext = theDoc->objects()->object(aNSDataLab);
           }
index 8a0b7b89f6d10bb8ee6cc6360eb848b3d39ea837..c0dde0f287ea7bea7ff7f529b0ed201c658cd845 100644 (file)
@@ -504,8 +504,14 @@ void Model_Session::processEvent(const std::shared_ptr<Events_Message>& theMessa
     if (theMessage->eventID() == kDeletedEvent) {
       std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleted =
         std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
-      if (aDeleted &&
-          aDeleted->groups().find(ModelAPI_ResultPart::group()) != aDeleted->groups().end())
+
+      std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>::const_iterator
+        aGIter = aDeleted->groups().cbegin();
+      for (; aGIter != aDeleted->groups().cend(); aGIter++) {
+        if (aGIter->second == ModelAPI_ResultPart::group())
+          break;
+      }
+      if (aGIter != aDeleted->groups().cend())
       {
          // check that the current feature of the session is still the active Part (even disabled)
         bool aFound = false;
index fbcb4a777d82158507d8a7c255f368f86522c4ae..9fde2d5abd040caf5bf8740c6f14e3fe4fe75a22 100644 (file)
@@ -57,7 +57,6 @@ SET(PROJECT_HEADERS
     ModelAPI_Plugin.h
     ModelAPI_Result.h
     ModelAPI_ResultBody.h
-    ModelAPI_ResultCompSolid.h
     ModelAPI_ResultConstruction.h
     ModelAPI_ResultField.h
     ModelAPI_ResultGroup.h
@@ -101,7 +100,6 @@ SET(PROJECT_SOURCES
     ModelAPI_Plugin.cpp
     ModelAPI_Result.cpp
     ModelAPI_ResultBody.cpp
-    ModelAPI_ResultCompSolid.cpp
     ModelAPI_ResultConstruction.cpp
     ModelAPI_ResultField.cpp
     ModelAPI_ResultGroup.cpp
index 61403edf66643f8052bee4eda00678c645211761..6199cb72ad2089ce9df65ba35b596c7ed031c740 100644 (file)
 %include "ModelAPI_ResultField.h"
 %include "ModelAPI_ResultParameter.h"
 %include "ModelAPI_Tools.h"
-%include "ModelAPI_ResultCompSolid.h"
 %include "ModelAPI_Folder.h"
 
 // std::list -> []
@@ -182,7 +181,6 @@ template<class T1, class T2> std::shared_ptr<T1> shared_ptr_cast(std::shared_ptr
 %template(modelAPI_ResultParameter) shared_ptr_cast<ModelAPI_ResultParameter, ModelAPI_Result>;
 %template(modelAPI_ResultGroup) shared_ptr_cast<ModelAPI_ResultPart, ModelAPI_ResultGroup>;
 %template(modelAPI_ResultField) shared_ptr_cast<ModelAPI_ResultPart, ModelAPI_ResultField>;
-%template(modelAPI_ResultCompSolid) shared_ptr_cast<ModelAPI_ResultCompSolid, ModelAPI_ResultBody>;
 
 // Attribute casts
 %template(modelAPI_AttributeDocRef)        shared_ptr_cast<ModelAPI_AttributeDocRef, ModelAPI_Attribute>;
index 904711ea2776363b14e1921203f8e0e2ebabce7b..5343ecfbd6052b338771bccb2f2a443ae2f8e5e4 100644 (file)
@@ -49,13 +49,13 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute
   ///           (used to remove immideately, without the following updates)
   /// \returns true if attribute was updated
   virtual bool setValue(
-    const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
+    const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
     const bool theTemporarily = false) = 0;
 
   /// Same as SetValue, but it takes an edge (on circular or elliptical curve)
   /// and stores the vertex of the central point (for ellipse the first or the second focus point)
   virtual void setValueCenter(
-    const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
+    const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
     const CenterType theCenterType,
     const bool theTemporarily = false) = 0;
 
@@ -72,6 +72,11 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute
   /// Returns the context of the selection (the whole shape owner)
   virtual ResultPtr context() = 0;
 
+  /// Returns the context of the selection if the whole feature was selected
+  virtual std::shared_ptr<ModelAPI_Feature> contextFeature() = 0;
+  /// Returns the context of the selection : result or feature
+  virtual std::shared_ptr<ModelAPI_Object> contextObject() = 0;
+
   /// Updates the underlied selection due to the changes in the referenced objects
   /// \returns false if update is failed
   virtual bool update() = 0;
index 7aba03eb562d112022f1c4709750b46ece63752b..7070744b6aa2a7dcf5402d029368f320806f9c16 100644 (file)
@@ -40,7 +40,7 @@ class ModelAPI_AttributeSelectionList : public ModelAPI_Attribute
   /// \param theSubShape selected sub-shape (if null, the whole context is selected)
   /// \param theTemporarily if it is true, do not store and name the added in the data framework
   ///           (used to remove immediately, without the following updates)
-  virtual void append(const ResultPtr& theContext,
+  virtual void append(const ObjectPtr& theContext,
                       const std::shared_ptr<GeomAPI_Shape>& theSubShape,
                       const bool theTemporarily = false) = 0;
 
@@ -67,7 +67,7 @@ class ModelAPI_AttributeSelectionList : public ModelAPI_Attribute
   /// \param theTemporarily if it is true, it checks also the temporary added item
   /// \returns true if the pair is found in the attirbute
   virtual bool isInList(
-    const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
+    const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
     const bool theTemporarily = false) = 0;
 
   /// The type of all elements selection
index e234aefe5a45721b42e061dde2a01a58b0e4702b..be23056ae6cae47231bd735fdae8a451234b2757 100644 (file)
@@ -114,6 +114,11 @@ public:
   //! \param theAllowFolder take into account grouping feature by folders
   virtual int size(const std::string& theGroupID, const bool theAllowFolder = false) = 0;
 
+  //! Returns the parent object of this child. This may be result or feature, parent of a
+  //! top result. Fast method, that uses internal data structure specifics.
+  virtual std::shared_ptr<ModelAPI_Object> parent(
+    const std::shared_ptr<ModelAPI_Object> theChild) = 0;
+
   //! Returns the feature that is currently edited in this document, normally
   //! this is the latest created feature
   //! \param theVisible use visible features only: flag is true for Object Browser functionality
index a7718d1de11721eaa0106e359d2666d62bc4b776..aa957fb723caabfbb3c68e86ba37be75159fdc57 100644 (file)
@@ -128,11 +128,9 @@ protected:
   virtual ~ModelAPI_ObjectDeletedMessage();
 
 public:
-  /// Returns the document that has been updated
-  virtual std::shared_ptr<ModelAPI_Document> document() const = 0;
-
   /// Returns the groups where the objects were deleted
-  virtual const std::set<std::string>& groups() const = 0;
+  virtual const std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string> >&
+    groups() const = 0;
 
   /// Creates the new empty message of this kind
   virtual std::shared_ptr<Events_MessageGroup> newEmpty() = 0;
index 4025d17b769b0a4e744586473d1c764982a9026e..ba28f8b90cf9c1bbda60e646be1d94b26b9d09b3 100644 (file)
 //
 
 #include "ModelAPI_ResultBody.h"
+
 #include <ModelAPI_BodyBuilder.h>
 #include <Events_Loop.h>
 #include <ModelAPI_Events.h>
 
 ModelAPI_ResultBody::ModelAPI_ResultBody()
-: myBuilder(0)
+  : myBuilder(0)
 {
   myConnect = ConnectionNotComputed;
 }
 
 ModelAPI_ResultBody::~ModelAPI_ResultBody()
 {
-  if (myBuilder)
-  delete myBuilder;
 }
 
 std::string ModelAPI_ResultBody::groupName()
@@ -41,7 +40,7 @@ std::string ModelAPI_ResultBody::groupName()
 }
 
 void ModelAPI_ResultBody::store(const std::shared_ptr<GeomAPI_Shape>& theShape,
-                                const bool theIsStoreSameShapes)
+  const bool theIsStoreSameShapes)
 {
   myBuilder->store(theShape, theIsStoreSameShapes);
   myConnect = ConnectionNotComputed;
@@ -50,10 +49,12 @@ void ModelAPI_ResultBody::store(const std::shared_ptr<GeomAPI_Shape>& theShape,
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
   static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
   aECreator->sendUpdated(data()->owner(), aRedispEvent);
+
+  updateSubs(theShape);
 }
 
 void ModelAPI_ResultBody::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& theFromShape,
-                                 const std::shared_ptr<GeomAPI_Shape>& theToShape)
+  const std::shared_ptr<GeomAPI_Shape>& theToShape)
 {
   myBuilder->storeGenerated(theFromShape, theToShape);
   myConnect = ConnectionNotComputed;
@@ -62,11 +63,13 @@ void ModelAPI_ResultBody::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& t
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
   static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
   aECreator->sendUpdated(data()->owner(), aRedispEvent);
+
+  updateSubs(theToShape);
 }
 
 void ModelAPI_ResultBody::storeModified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
-                                 const std::shared_ptr<GeomAPI_Shape>& theNewShape,
-                            const int theDecomposeSolidsTag)
+  const std::shared_ptr<GeomAPI_Shape>& theNewShape,
+  const int theDecomposeSolidsTag)
 {
   myBuilder->storeModified(theOldShape, theNewShape, theDecomposeSolidsTag);
   myConnect = ConnectionNotComputed;
@@ -75,6 +78,8 @@ void ModelAPI_ResultBody::storeModified(const std::shared_ptr<GeomAPI_Shape>& th
   static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
   static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
   aECreator->sendUpdated(data()->owner(), aRedispEvent);
+
+  updateSubs(theNewShape);
 }
 
 void ModelAPI_ResultBody::storeWithoutNaming(const std::shared_ptr<GeomAPI_Shape>& theShape)
@@ -94,74 +99,74 @@ std::shared_ptr<GeomAPI_Shape> ModelAPI_ResultBody::shape()
 }
 
 void ModelAPI_ResultBody::generated(const std::shared_ptr<GeomAPI_Shape>& theNewShape,
-    const std::string& theName, const int theTag)
+  const std::string& theName, const int theTag)
 {
   myBuilder->generated(theNewShape, theName, theTag);
 }
 
 void ModelAPI_ResultBody::generated(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
-    const std::shared_ptr<GeomAPI_Shape>& theNewShape, const std::string& theName,
-    const int theTag)
+  const std::shared_ptr<GeomAPI_Shape>& theNewShape, const std::string& theName,
+  const int theTag)
 {
   myBuilder->generated(theOldShape, theNewShape, theName, theTag);
 }
 
 void ModelAPI_ResultBody::modified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
-    const std::shared_ptr<GeomAPI_Shape>& theNewShape, const std::string& theName,
-    const int theTag)
+  const std::shared_ptr<GeomAPI_Shape>& theNewShape, const std::string& theName,
+  const int theTag)
 {
   myBuilder->modified(theOldShape, theNewShape, theName, theTag);
 }
 
 
 void ModelAPI_ResultBody::deleted(
-    const std::shared_ptr<GeomAPI_Shape>& theOldShape, const int theTag)
+  const std::shared_ptr<GeomAPI_Shape>& theOldShape, const int theTag)
 {
   myBuilder->deleted(theOldShape, theTag);
 }
 
-void ModelAPI_ResultBody::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS,
-                                  std::shared_ptr<GeomAPI_Shape>  theShapeIn,
-                                  const int  theKindOfShape,
-                                  const int  theTag)
+void ModelAPI_ResultBody::loadDeletedShapes(GeomAlgoAPI_MakeShape* theMS,
+  std::shared_ptr<GeomAPI_Shape>  theShapeIn,
+  const int  theKindOfShape,
+  const int  theTag)
 {
   myBuilder->loadDeletedShapes(theMS, theShapeIn, theKindOfShape, theTag);
 }
 
-void ModelAPI_ResultBody::loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* theMS,
-    std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
-    const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
-    const bool theIsStoreSeparate,
-    const bool theIsStoreAsGenerated,
-    const bool /*theSplitInSubs*/)
+void ModelAPI_ResultBody::loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS,
+  std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
+  const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
+  const bool theIsStoreSeparate,
+  const bool theIsStoreAsGenerated,
+  const bool /*theSplitInSubs*/)
 {
   myBuilder->loadAndOrientModifiedShapes(
     theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
     theIsStoreAsGenerated);
 }
 
-void ModelAPI_ResultBody::loadAndOrientGeneratedShapes (GeomAlgoAPI_MakeShape* theMS,
-    std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape,
-    const int  theTag, const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes)
+void ModelAPI_ResultBody::loadAndOrientGeneratedShapes(GeomAlgoAPI_MakeShape* theMS,
+  std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape,
+  const int  theTag, const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes)
 {
   myBuilder->loadAndOrientGeneratedShapes(
     theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes);
 }
 
 void ModelAPI_ResultBody::loadFirstLevel(std::shared_ptr<GeomAPI_Shape> theShape,
-    const std::string& theName, int&  theTag)
+  const std::string& theName, int&  theTag)
 {
   myBuilder->loadFirstLevel(theShape, theName, theTag);
 }
 
 void ModelAPI_ResultBody::loadDisconnectedEdges(std::shared_ptr<GeomAPI_Shape> theShape,
-    const std::string& theName, int&  theTag)
+  const std::string& theName, int&  theTag)
 {
   myBuilder->loadDisconnectedEdges(theShape, theName, theTag);
 }
 
 void ModelAPI_ResultBody::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape> theShape,
-    const std::string& theName,int&  theTag)
+  const std::string& theName, int&  theTag)
 {
   myBuilder->loadDisconnectedVertexes(theShape, theName, theTag);
 }
@@ -173,3 +178,10 @@ bool ModelAPI_ResultBody::isConnectedTopology()
   }
   return myConnect == IsConnected;
 }
+
+void ModelAPI_ResultBody::setDisplayed(const bool theDisplay)
+{
+  ModelAPI_Result::setDisplayed(theDisplay);
+  for (int i = 0; i < numberOfSubs(); i++)
+    subResult(i)->setDisplayed(theDisplay);
+}
index 98a4b6a290c53f76da28f7e60c94c1f3d8597b3f..0ffb2422a3e9c67f7c68e462ec679f1fde22466d 100644 (file)
@@ -36,11 +36,27 @@ class GeomAlgoAPI_MakeShape;
 * Provides a shape that may be displayed in the viewer.
 * May provide really huge results, so, working with this kind
 * of result must be optimized.
+* Also provides a conainer of sub-body result in case it is compound or compsolid.
 */
 class ModelAPI_ResultBody : public ModelAPI_Result
 {
+public:
+  /// Iternal enumeration for storage the information of connected topology flag
+  enum ConnectedTopologyFlag {
+    ConnectionNotComputed, ///< not yet computed
+    IsConnected,           ///< the topology is connected
+    IsNotConnected         ///< the topology is connected
+  };
+
+protected:
+  /// Keeps (not persistently) the connected topology flag
+  ConnectedTopologyFlag myConnect;
+
+  ModelAPI_BodyBuilder* myBuilder; ///< provides the body processing in naming shape
+
 public:
   MODELAPI_EXPORT virtual ~ModelAPI_ResultBody();
+
   /// Returns the group identifier of this result
   MODELAPI_EXPORT virtual std::string groupName();
 
@@ -64,21 +80,23 @@ public:
     return "0.0001";
   }
 
-  /// Iternal enumeration for storage the information of connected topology flag
-  enum ConnectedTopologyFlag {
-    ConnectionNotComputed, ///< not yet computed
-    IsConnected,           ///< the topology is connected
-    IsNotConnected         ///< the topology is connected
-  };
-  /// Keeps (not persistently) the connected topology flag
-  ConnectedTopologyFlag myConnect;
+  /// Returns the number of sub-elements
+  MODELAPI_EXPORT virtual int numberOfSubs(bool forTree = false) const = 0;
+
+  /// Returns the sub-result by zero-base index
+  MODELAPI_EXPORT virtual std::shared_ptr<ModelAPI_ResultBody> subResult(
+    const int theIndex, bool forTree = false) const = 0;
+
+  /// Returns true if feature or reuslt belong to this composite feature as subs
+  /// Returns theIndex - zero based index of sub if found
+  MODELAPI_EXPORT virtual bool isSub(ObjectPtr theObject, int& theIndex) const = 0;
 
   /// \brief Stores the shape (called by the execution method).
   /// param[in] theShape shape to store.
   /// param[in] theIsStoreSameShapes if false stores reference to the same shape
   ///                                if it is already in document.
   MODELAPI_EXPORT virtual void store(const std::shared_ptr<GeomAPI_Shape>& theShape,
-                                     const bool theIsStoreSameShapes = true);
+    const bool theIsStoreSameShapes = true);
 
   /// Stores the generated shape (called by the execution method).
   MODELAPI_EXPORT virtual void storeGenerated(const std::shared_ptr<GeomAPI_Shape>& theFromShape,
@@ -119,19 +137,20 @@ public:
     const std::shared_ptr<GeomAPI_Shape>& theOldShape, const int theTag = 1);
 
   /// load deleted shapes
-  MODELAPI_EXPORT virtual void loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS,
-                                  std::shared_ptr<GeomAPI_Shape>  theShapeIn,
-                                  const int  theKindOfShape,
-                                  const int  theTag);
+  MODELAPI_EXPORT virtual void loadDeletedShapes(GeomAlgoAPI_MakeShape* theMS,
+    std::shared_ptr<GeomAPI_Shape>  theShapeIn,
+    const int  theKindOfShape,
+    const int  theTag);
+
   /// load and orient modified shapes
-  MODELAPI_EXPORT virtual void loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* theMS,
+  MODELAPI_EXPORT virtual void loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS,
     std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
     const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
-    const bool theIsStoreSeparate = false,
-    const bool theIsStoreAsGenerated = false,
+    const bool theIsStoreSeparate = false, const bool theIsStoreAsGenerated = false,
     const bool theSplitInSubs = false);
+
   /// load and orient generated shapes
-  MODELAPI_EXPORT virtual void loadAndOrientGeneratedShapes (GeomAlgoAPI_MakeShape* theMS,
+  MODELAPI_EXPORT virtual void loadAndOrientGeneratedShapes(GeomAlgoAPI_MakeShape* theMS,
     std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape,
     const int  theTag, const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes);
 
@@ -145,7 +164,7 @@ public:
 
   /// load disconnected vetexes
   MODELAPI_EXPORT virtual void loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape> theShape,
-    const std::string& theName,int&  theTag);
+    const std::string& theName, int&  theTag);
 
   /// Returns true if the latest modification of this body in the naming history
   // is equal to the given shape
@@ -155,11 +174,16 @@ public:
   /// so it is more effective to use this method than directly GeomAPI_Shape.
   MODELAPI_EXPORT virtual bool isConnectedTopology();
 
+  /// Set displayed flag to the result and all sub results
+  /// \param theDisplay a boolean value
+  MODELAPI_EXPORT virtual void setDisplayed(const bool theDisplay);
+
 protected:
   /// Default constructor accessible only from Model_Objects
   MODELAPI_EXPORT ModelAPI_ResultBody();
 
-  ModelAPI_BodyBuilder* myBuilder; ///< provides the body processing in naming shape
+  /// Updates the sub-bodies if shape of this object is compsolid or compound
+  virtual void updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisShape) = 0;
 };
 
 //! Pointer on feature object
diff --git a/src/ModelAPI/ModelAPI_ResultCompSolid.cpp b/src/ModelAPI/ModelAPI_ResultCompSolid.cpp
deleted file mode 100755 (executable)
index e1fa263..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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_ResultCompSolid.h"
-
-ModelAPI_ResultCompSolid::~ModelAPI_ResultCompSolid()
-{
-}
-
-void ModelAPI_ResultCompSolid::setDisplayed(const bool theDisplay)
-{
-  ModelAPI_ResultBody::setDisplayed(theDisplay);
-  for (int i = 0; i < numberOfSubs(); i++)
-    subResult(i)->setDisplayed(theDisplay);
-}
diff --git a/src/ModelAPI/ModelAPI_ResultCompSolid.h b/src/ModelAPI/ModelAPI_ResultCompSolid.h
deleted file mode 100755 (executable)
index 70abc72..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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_ResultCompSolid_H_
-#define ModelAPI_ResultCompSolid_H_
-
-#include "ModelAPI_Result.h"
-#include "ModelAPI_ResultBody.h"
-#include <string>
-
-/**\class ModelAPI_ResultCompSolid
-* \ingroup DataModel
-* \brief The comp solid (container of results) result of a feature.
-*
-* Provides a conainer of body result that may be displayed in the viewer.
-*/
-class ModelAPI_ResultCompSolid : public ModelAPI_ResultBody
-{
-public:
-  MODELAPI_EXPORT virtual ~ModelAPI_ResultCompSolid();
-  /// Returns the group identifier of this result
-
-  /// Returns the number of sub-elements
-  virtual int numberOfSubs(bool forTree = false) const = 0;
-
-  /// Returns the sub-result by zero-base index
-  virtual std::shared_ptr<ModelAPI_ResultBody> subResult(const int theIndex,
-                                                         bool forTree = false) const = 0;
-
-  /// Returns true if feature or reuslt belong to this composite feature as subs
-  /// Returns theIndex - zero based index of sub if found
-  virtual bool isSub(ObjectPtr theObject, int& theIndex) const = 0;
-
-  /// Set displayed flag to the result and all sub results
-  /// \param theDisplay a boolean value
-  MODELAPI_EXPORT virtual void setDisplayed(const bool theDisplay);
-
-protected:
-};
-
-//! Pointer on feature object
-typedef std::shared_ptr<ModelAPI_ResultCompSolid> ResultCompSolidPtr;
-
-#endif
index b656c3fb7902d413adcd659f8bcab83c821d7e18..a1f4ef0640583075e4dd4eee980a3049f3309821 100755 (executable)
@@ -24,7 +24,7 @@
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Object.h>
 #include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultParameter.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_AttributeDocRef.h>
@@ -265,66 +265,64 @@ CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature)
   return CompositeFeaturePtr(); // not found
 }
 
-ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub)
+ResultBodyPtr bodyOwner(const ResultPtr& theSub, const bool theRoot)
 {
-  int anIndex;
-  ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theSub);
-  if (aBody.get()) {
-    FeaturePtr aFeatureOwner = aBody->document()->feature(aBody);
-    if (aFeatureOwner.get()) {
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
-        aFeatureOwner->results().cbegin();
-      for(; aResIter != aFeatureOwner->results().cend(); aResIter++) {
-        ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIter);
-        if (aComp && aComp->isSub(aBody, anIndex))
-          return aComp;
+  if (theSub.get()) {
+    ObjectPtr aParent = theSub->document()->parent(theSub);
+    if (aParent.get()) {
+      if (theRoot) { // try to find parent of parent
+        ResultPtr aResultParent = std::dynamic_pointer_cast<ModelAPI_Result>(aParent);
+        ResultBodyPtr aGrandParent = bodyOwner(aResultParent, true);
+        if (aGrandParent.get())
+          aParent = aGrandParent;
       }
+      return std::dynamic_pointer_cast<ModelAPI_ResultBody>(aParent);
     }
   }
-  return ResultCompSolidPtr(); // not found
+  return ResultBodyPtr(); // not found
 }
 
-int compSolidIndex(const ResultPtr& theSub)
+int bodyIndex(const ResultPtr& theSub)
 {
   int anIndex = -1;
-  ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theSub);
-  if (aBody.get()) {
-    FeaturePtr aFeatureOwner = aBody->document()->feature(aBody);
-    if (aFeatureOwner.get()) {
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
-        aFeatureOwner->results().cbegin();
-      for(; aResIter != aFeatureOwner->results().cend(); aResIter++) {
-        ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIter);
-        if (aComp && aComp->isSub(aBody, anIndex))
-          return anIndex;
-      }
-    }
+  ResultBodyPtr aParent = bodyOwner(theSub);
+  if (aParent.get()) {
+    ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theSub);
+    if (aBody.get() && aParent->isSub(aBody, anIndex))
+      return anIndex;
   }
   return anIndex; // not found
 }
 
 bool hasSubResults(const ResultPtr& theResult)
 {
-  ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theResult);
+  ResultBodyPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
   return aCompSolid.get() && aCompSolid->numberOfSubs() > 0;
 }
 
+void allSubs(const ResultBodyPtr& theResult, std::list<ResultPtr>& theResults) {
+  // iterate sub-bodies of compsolid
+  ResultBodyPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+  if (aComp.get()) {
+    int aNumSub = aComp->numberOfSubs();
+    for (int a = 0; a < aNumSub; a++) {
+      ResultBodyPtr aSub = aComp->subResult(a);
+      theResults.push_back(aSub);
+      allSubs(aSub, theResults);
+    }
+  }
+}
+
 void allResults(const FeaturePtr& theFeature, std::list<ResultPtr>& theResults)
 {
   if (!theFeature.get()) // safety: for empty feature no results
     return;
   const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
-  std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+  std::list<ResultPtr>::const_iterator aRIter = aResults.begin();
   for (; aRIter != aResults.cend(); aRIter++) {
     theResults.push_back(*aRIter);
-    // iterate sub-bodies of compsolid
-    ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aRIter);
-    if (aComp.get()) {
-      int aNumSub = aComp->numberOfSubs();
-      for(int a = 0; a < aNumSub; a++) {
-        theResults.push_back(aComp->subResult(a));
-      }
-    }
+    ResultBodyPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRIter);
+    allSubs(aResult, theResults);
   }
 }
 
@@ -606,58 +604,61 @@ void getConcealedResults(const FeaturePtr& theFeature,
   }
 }
 
-std::pair<std::string, bool> getDefaultName(
-    const std::shared_ptr<ModelAPI_Result>& theResult,
-    const int theResultIndex)
+std::pair<std::string, bool> getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
+                                            const bool theInherited)
 {
   typedef std::list< std::pair < std::string, std::list<ObjectPtr> > > ListOfReferences;
 
   SessionPtr aSession = ModelAPI_Session::get();
-  FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner());
 
-  ResultCompSolidPtr aCompSolidRes = compSolidOwner(theResult);
-  if (aCompSolidRes) {
+  ResultBodyPtr anOwnerRes = bodyOwner(theResult);
+  if (anOwnerRes) {
     // names of sub-solids in CompSolid should be default (for example,
     // result of boolean operation 'Boolean_1_1' is a CompSolid which is renamed to 'MyBOOL',
     // however, sub-elements of 'MyBOOL' should be named 'Boolean_1_1_1', 'Boolean_1_1_2' etc.)
     std::ostringstream aDefaultName;
-    aDefaultName << anOwner->name();
-    // compute default name of CompSolid (name of feature + index of CompSolid's result)
-    int aCompSolidResultIndex = 0;
-    const std::list<ResultPtr>& aResults = anOwner->results();
-    for (std::list<ResultPtr>::const_iterator anIt = aResults.begin();
-         anIt != aResults.end(); ++anIt, ++aCompSolidResultIndex)
-      if (aCompSolidRes == *anIt)
-        break;
-    aDefaultName << "_" << (aCompSolidResultIndex + 1) << "_" << (theResultIndex + 1);
+    aDefaultName << getDefaultName(anOwnerRes).first;
+    aDefaultName << "_" << (bodyIndex(theResult) + 1);
     return std::pair<std::string, bool>(aDefaultName.str(), false);
   }
 
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner());
   DataPtr aData = anOwner->data();
 
   ListOfReferences aReferences;
-  aData->referencesToObjects(aReferences);
-
   // find first result with user-defined name
   ListOfReferences::const_iterator aFoundRef = aReferences.end();
-  for (ListOfReferences::const_iterator aRefIt = aReferences.begin();
-       aRefIt != aReferences.end(); ++aRefIt) {
-    bool isConcealed = aSession->validators()->isConcealed(anOwner->getKind(), aRefIt->first);
-    bool isMainArg = isConcealed &&
-                     aSession->validators()->isMainArgument(anOwner->getKind(), aRefIt->first);
-    if (isConcealed) {
-      // check the referred object is a Body
-      // (for example, ExtrusionCut has a sketch as a first attribute which is concealing)
-      bool isBody = aRefIt->second.size() > 1 || (aRefIt->second.size() == 1 &&
-                    aRefIt->second.front()->groupName() == ModelAPI_ResultBody::group());
-      if (isBody && (isMainArg || aFoundRef == aReferences.end() ||
-          aData->isPrecedingAttribute(aRefIt->first, aFoundRef->first)))
-        aFoundRef = aRefIt;
-
-      if (isMainArg)
-        break;
+  if (theInherited) {
+    aData->referencesToObjects(aReferences);
+
+    for (ListOfReferences::const_iterator aRefIt = aReferences.begin();
+         aRefIt != aReferences.end(); ++aRefIt) {
+      bool isConcealed = aSession->validators()->isConcealed(anOwner->getKind(), aRefIt->first);
+      bool isMainArg = isConcealed &&
+                       aSession->validators()->isMainArgument(anOwner->getKind(), aRefIt->first);
+      if (isConcealed) {
+        // check the referred object is a Body
+        // (for example, ExtrusionCut has a sketch as a first attribute which is concealing)
+        bool isBody = aRefIt->second.size() > 1 || (aRefIt->second.size() == 1 &&
+                      aRefIt->second.front()->groupName() == ModelAPI_ResultBody::group());
+        if (isBody && (isMainArg || aFoundRef == aReferences.end() ||
+            aData->isPrecedingAttribute(aRefIt->first, aFoundRef->first)))
+          aFoundRef = aRefIt;
+
+        if (isMainArg)
+          break;
+      }
     }
   }
+  // get the result number in the feature
+  int anIndexInOwner = 0;
+  const std::list<ResultPtr>& anOwnerResults = anOwner->results();
+  std::list<ResultPtr>::const_iterator aResIt = anOwnerResults.cbegin();
+  for(; aResIt != anOwnerResults.cend(); aResIt++) {
+    if(*aResIt == theResult)
+      break;
+    anIndexInOwner++;
+  }
 
   // find an object which is concealed by theResult
   if (aFoundRef != aReferences.end() && !aFoundRef->second.empty()) {
@@ -665,12 +666,12 @@ std::pair<std::string, bool> getDefaultName(
     std::map<ResultPtr, int> aNbRefToObject;
     // search the object by result index
     std::list<ObjectPtr>::const_iterator anObjIt = aFoundRef->second.begin();
-    int aResultIndex = theResultIndex;
+    int aResultIndex = anIndexInOwner;
     while (--aResultIndex >= 0) {
       ResultPtr aCurRes = std::dynamic_pointer_cast<ModelAPI_Result>(*anObjIt);
-      ResultCompSolidPtr aParentCompSolid = ModelAPI_Tools::compSolidOwner(aCurRes);
-      if (aParentCompSolid)
-        aCurRes = aParentCompSolid;
+      ResultBodyPtr aParentBody = ModelAPI_Tools::bodyOwner(aCurRes);
+      if (aParentBody)
+        aCurRes = aParentBody;
       if (aNbRefToObject.find(aCurRes) == aNbRefToObject.end())
         aNbRefToObject[aCurRes] = 1;
       else
@@ -686,9 +687,9 @@ std::pair<std::string, bool> getDefaultName(
     if ((*anObjIt)->groupName() == ModelAPI_ResultBody::group()) {
       // check the result is part of CompSolid
       ResultPtr anObjRes = std::dynamic_pointer_cast<ModelAPI_Result>(*anObjIt);
-      ResultCompSolidPtr aParentCompSolid = ModelAPI_Tools::compSolidOwner(anObjRes);
-      if (aParentCompSolid)
-        anObjRes = aParentCompSolid;
+      ResultBodyPtr aParentBody = ModelAPI_Tools::bodyOwner(anObjRes);
+      if (aParentBody)
+        anObjRes = aParentBody;
 
       // return name of reference result only if it has been renamed by the user,
       // in other case compose a default name
@@ -711,48 +712,9 @@ std::pair<std::string, bool> getDefaultName(
   aDefaultName << anOwner->name();
   // if there are several results (issue #899: any number of result),
   // add unique prefix starting from second
-  if (theResultIndex > 0 || theResult->groupName() == ModelAPI_ResultBody::group())
-    aDefaultName << "_" << theResultIndex + 1;
+  if (anIndexInOwner > 0 || theResult->groupName() == ModelAPI_ResultBody::group())
+    aDefaultName << "_" << anIndexInOwner + 1;
   return std::pair<std::string, bool>(aDefaultName.str(), false);
 }
 
-std::string getDefaultName(const ResultPtr& theResult)
-{
-  FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner());
-
-  // names of sub-solids in CompSolid should be default (for example,
-  // result of boolean operation 'Boolean_1_1' is a CompSolid which is renamed to 'MyBOOL',
-  // however, sub-elements of 'MyBOOL' should be named 'Boolean_1_1_1', 'Boolean_1_1_2' etc.)
-  std::ostringstream aDefaultName;
-  aDefaultName << anOwner->name();
-
-  ResultPtr aResToSearch = theResult;
-  ResultCompSolidPtr aCompSolidRes = compSolidOwner(theResult);
-  if (aCompSolidRes)
-    aResToSearch = aCompSolidRes;
-
-  // obtain index of result
-  int aResIndex = 1;
-  const std::list<ResultPtr>& aResults = anOwner->results();
-  for (std::list<ResultPtr>::const_iterator anIt = aResults.begin();
-       anIt != aResults.end(); ++anIt, ++aResIndex)
-    if (aResToSearch == *anIt)
-      break;
-
-  // compute default name of CompSolid (name of feature + index of CompSolid's result)
-  aDefaultName << "_" << aResIndex;
-
-  if (aCompSolidRes) {
-    // obtain index of result in compsolid and compose a default name
-    int aNbSubs = aCompSolidRes->numberOfSubs();
-    for (int anIndex = 0; anIndex < aNbSubs; ++anIndex)
-      if (aCompSolidRes->subResult(anIndex) == theResult) {
-        aDefaultName << "_" << (anIndex + 1);
-        break;
-      }
-  }
-
-  return aDefaultName.str();
-}
-
 } // namespace ModelAPI_Tools
index 907cc7b974a9df0f996c51c699a4024566878418..e302d19a0634191fed1345f06ec8688ba64431ac 100755 (executable)
@@ -28,7 +28,7 @@ class ModelAPI_Document;
 class ModelAPI_Feature;
 class ModelAPI_Result;
 class ModelAPI_ResultParameter;
-class ModelAPI_ResultCompSolid;
+class ModelAPI_ResultBody;
 
 class GeomAPI_Shape;
 
@@ -101,17 +101,18 @@ MODELAPI_EXPORT std::shared_ptr<ModelAPI_CompositeFeature> compositeOwner(
                                         const std::shared_ptr<ModelAPI_Feature>& theFeature);
 
 /*!
- * Returns the compsolid result - parent of this result.
- * \param theSub the sub-element of comp-solid
+ * Returns the result - parent of this result.
+ * \param theSub the sub-element of composit result
+ * \param theRoot if it is true, returns the root father
  * \returns null if it is not sub-element of composite
  */
-MODELAPI_EXPORT std::shared_ptr<ModelAPI_ResultCompSolid> compSolidOwner(
-                                            const std::shared_ptr<ModelAPI_Result>& theSub);
+MODELAPI_EXPORT std::shared_ptr<ModelAPI_ResultBody>
+  bodyOwner(const std::shared_ptr<ModelAPI_Result>& theSub, const bool theRoot = false);
 /*!
- * Returns index of this result in parent (if parent exists, returned by compSolidOwner)
+ * Returns index of this result in parent (if parent exists, returned by bodyOwner)
  * \returns zero-base index, or -1 if not found
  */
-MODELAPI_EXPORT int compSolidIndex(const std::shared_ptr<ModelAPI_Result>& theSub);
+MODELAPI_EXPORT int bodyIndex(const std::shared_ptr<ModelAPI_Result>& theSub);
 
 /*!
 * Returns true if the result contains a not empty list of sub results.
@@ -121,6 +122,12 @@ MODELAPI_EXPORT int compSolidIndex(const std::shared_ptr<ModelAPI_Result>& theSu
 */
 MODELAPI_EXPORT bool hasSubResults(const std::shared_ptr<ModelAPI_Result>& theResult);
 
+/*!
+*  collects recursively all subs of the given result
+*/
+MODELAPI_EXPORT void allSubs(const std::shared_ptr<ModelAPI_ResultBody>& theResult,
+                             std::list<std::shared_ptr<ModelAPI_Result> >& theResults);
+
 /*!
 * Adds the results of the given feature to theResults list: including disabled and sub-results
 */
@@ -187,17 +194,12 @@ MODELAPI_EXPORT void findRefsToFeatures(
 MODELAPI_EXPORT void getConcealedResults(const std::shared_ptr<ModelAPI_Feature>& theFeature,
                                    std::list<std::shared_ptr<ModelAPI_Result> >& theResults);
 
-/*! Return the default name of the result according the features it depends.
+/*! Return the default name of the result according the features it depends or name of the feature.
  *  Return also whether the name is get from the concealing result of parent object
  *  (means that concealing result has user-defined name).
  */
 MODELAPI_EXPORT std::pair<std::string, bool> getDefaultName(
-    const std::shared_ptr<ModelAPI_Result>& theResult,
-    const int theResultIndex);
-
-/*! Return the default name of the result according to name of the feature.
- */
-MODELAPI_EXPORT std::string getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult);
+  const std::shared_ptr<ModelAPI_Result>& theResult, const bool theInherited = true);
 }
 
 #endif
index e9d740ce076c8dedb9bd0c6e5a909c048cd52d8f..320d3771ae7c656321630ab8ef716c52a68c6f0f 100644 (file)
@@ -59,7 +59,6 @@
   #include "ModelAPI_ResultGroup.h"
   #include "ModelAPI_ResultField.h"
   #include "ModelAPI_Tools.h"
-  #include "ModelAPI_ResultCompSolid.h"
   #include "ModelAPI_Folder.h"
 
   #include <memory>
index 985e6761ea60da801a77c61a13e2fcb18134a133..8bc41417be4434a04555ce2e0e807a020e4416ce 100644 (file)
@@ -49,7 +49,6 @@
 #include <ModelAPI_Folder.h>
 #include <ModelAPI_Result.h>
 #include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_Tools.h>
@@ -216,32 +215,15 @@ void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature)
 
   // Save only names of results which is not correspond to default feature name
   const std::list<ResultPtr>& aResults = theFeature->results();
-  std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
-  for (int i = 0; aResIt != aResults.end(); ++aResIt, ++i) {
-    std::pair<std::string, bool> aName = ModelAPI_Tools::getDefaultName(*aResIt, i);
+  std::list<ResultPtr> allRes;
+  ModelAPI_Tools::allResults(theFeature, allRes);
+  for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+    std::pair<std::string, bool> aName = ModelAPI_Tools::getDefaultName(*aRes);
     std::string aDefaultName = aName.first;
-    std::string aResName = (*aResIt)->data()->name();
-
+    std::string aResName = (*aRes)->data()->name();
     bool isUserDefined = !(isFeatureDefaultName && aDefaultName == aResName);
-
-    myNames[*aResIt] = EntityName(aResName,
-        (isUserDefined ? aResName : std::string()), !isUserDefined);
-
-    // check names of sub-results for CompSolid
-    ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIt);
-    if (aCompSolid) {
-      int aNbSubs = aCompSolid->numberOfSubs();
-      for (int j = 0; j < aNbSubs; ++j) {
-        ResultPtr aSub = aCompSolid->subResult(j);
-        std::string aSubName = aSub->data()->name();
-        aName = ModelAPI_Tools::getDefaultName(aSub, j);
-        aDefaultName = aName.first;
-
-        bool isUserDefinedSubName = isUserDefined || aDefaultName != aSubName;
-        myNames[aSub] = EntityName(aSubName,
-            (isUserDefinedSubName ? aSubName : std::string()), !isUserDefinedSubName);
-      }
-    }
+    myNames[*aRes] =
+      EntityName(aResName, (isUserDefined ? aResName : std::string()), !isUserDefined);
   }
 }
 
@@ -783,24 +765,12 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity
     bool isUserDefinedName = !myNames[theEntity].myIsDefault;
     // store results if they have user-defined names or colors
     std::list<ResultPtr> aResultsWithNameOrColor;
-    const std::list<ResultPtr>& aResults = theEntity->results();
-    std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
-    for (; aResIt != aResults.end(); ++aResIt) {
-      if (!myNames[*aResIt].myIsDefault || !isDefaultColor(*aResIt) ||
-          !isDefaultDeflection(*aResIt) || !isDefaultTransparency(*aResIt))
-        aResultsWithNameOrColor.push_back(*aResIt);
-
-      ResultCompSolidPtr aCompSolid =
-          std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIt);
-      if (aCompSolid) {
-        int aNbSubs = aCompSolid->numberOfSubs();
-        for (int i = 0; i < aNbSubs; ++i) {
-          ResultPtr aCurRes = aCompSolid->subResult(i);
-          if (!myNames[aCurRes].myIsDefault || !isDefaultColor(aCurRes) ||
-              !isDefaultDeflection(aCurRes) || !isDefaultTransparency(aCurRes))
-            aResultsWithNameOrColor.push_back(aCurRes);
-        }
-      }
+    std::list<ResultPtr> allRes;
+    ModelAPI_Tools::allResults(theEntity, allRes);
+    for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+      if(!myNames[*aRes].myIsDefault || !isDefaultColor(*aRes) ||
+         !isDefaultDeflection(*aRes) || !isDefaultTransparency(*aRes))
+        aResultsWithNameOrColor.push_back(*aRes);
     }
     // store just dumped entity to stack
     if (myEntitiesStack.empty() || myEntitiesStack.top().myEntity != theEntity)
@@ -815,37 +785,40 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity
 
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ResultPtr& theResult)
 {
+  // iterate in the structure of sub-results to the parent
+  ResultPtr aCurRes = theResult;
   FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
-  int anIndex = 0;
-  int aSubIndex = -1;
-  std::list<ResultPtr> aResults = aFeature->results();
-  for(std::list<ResultPtr>::const_iterator
-      anIt = aResults.cbegin(); anIt != aResults.cend(); ++anIt, ++anIndex) {
-    if(theResult->isSame(*anIt)) {
-      break;
-    }
-
-    ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*anIt);
-    if (aCompSolid) {
-      int aNbSubs = aCompSolid->numberOfSubs();
-      for (aSubIndex = 0; aSubIndex < aNbSubs; ++aSubIndex)
-        if (theResult->isSame(aCompSolid->subResult(aSubIndex)))
+  std::list<int> anIndices; // indexes of results in the parent result, starting from topmost
+  while(aCurRes.get()) {
+    ResultBodyPtr aParent = ModelAPI_Tools::bodyOwner(aCurRes);
+    if (aParent) {
+      anIndices.push_front(ModelAPI_Tools::bodyIndex(aCurRes));
+    } else { // index of the result in the feature
+      std::list<ResultPtr>::const_iterator aRes = aFeature->results().cbegin();
+      for(int anIndex = 0; aRes != aFeature->results().cend(); aRes++, anIndex++) {
+        if (*aRes == aCurRes) {
+          anIndices.push_front(anIndex);
           break;
-      if (aSubIndex < aNbSubs)
-        break;
-      aSubIndex = -1;
+        }
+      }
     }
+    aCurRes = aParent;
   }
 
   myDumpBuffer << name(aFeature);
-  if(anIndex == 0) {
-    myDumpBuffer << ".result()";
-  } else {
-    myDumpBuffer << ".results()[" << anIndex << "]";
-  }
-  if (aSubIndex >= 0) {
-    myDumpBuffer << ".subResult(" << aSubIndex << ")";
+  for (std::list<int>::iterator anI = anIndices.begin(); anI != anIndices.end(); anI++) {
+    if (anI == anIndices.begin()) {
+      if(*anI == 0) {
+        myDumpBuffer << ".result()";
+      }
+      else {
+        myDumpBuffer << ".results()[" << *anI << "]";
+      }
+    } else {
+      myDumpBuffer << ".subResult(" << *anI << ")";
+    }
   }
+
   return *this;
 }
 
index ca9422c18b1152224f2f8306c803dd29f06c62a8..c87b99fe9a078dd0e9c81a09ef52869521e35872 100644 (file)
@@ -25,7 +25,8 @@
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Feature.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
+
 //--------------------------------------------------------------------------------------
 
 //--------------------------------------------------------------------------------------
@@ -181,12 +182,11 @@ int ModelHighAPI_Selection::numberOfSubs() const
   if (myVariantType != VT_ResultSubShapePair)
     return 0;
 
-  ResultCompSolidPtr aCompSolid =
-      std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(myResultSubShapePair.first);
-  if (!aCompSolid)
+  ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myResultSubShapePair.first);
+  if (!aBody.get())
     return 0;
 
-  return aCompSolid->numberOfSubs();
+  return aBody->numberOfSubs();
 }
 
 ModelHighAPI_Selection ModelHighAPI_Selection::subResult(int theIndex) const
@@ -194,13 +194,12 @@ ModelHighAPI_Selection ModelHighAPI_Selection::subResult(int theIndex) const
   if (myVariantType != VT_ResultSubShapePair)
     return ModelHighAPI_Selection();
 
-  ResultCompSolidPtr aCompSolid =
-      std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(myResultSubShapePair.first);
-  if (!aCompSolid)
+  ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myResultSubShapePair.first);
+  if (!aBody)
     return ModelHighAPI_Selection();
-  if (theIndex >= aCompSolid->numberOfSubs())
+  if (theIndex >= aBody->numberOfSubs())
     return ModelHighAPI_Selection();
 
-  ResultBodyPtr aResult = aCompSolid->subResult(theIndex);
+  ResultBodyPtr aResult = aBody->subResult(theIndex);
   return ModelHighAPI_Selection(aResult, aResult->shape());
 }
index 954e72f0349dc6228c3743864dbe8aee0e7be6de..bf7c8bbcff49d792b20dec4c1c682d2891af9441 100644 (file)
 #define ModuleBase_ITreeNode_H
 
 #include "ModuleBase.h"
+#include "ModuleBase_Definitions.h"
 
 #include <ModelAPI_Object.h>
+#include <ModelAPI_Document.h>
 
 #include <QList>
 #include <QString>
 #include <QIcon>
+#include <QVariant>
 
 class ModuleBase_ITreeNode;
+class ModuleBase_IWorkshop;
 
 typedef QList<ModuleBase_ITreeNode*> QTreeNodesList;
 
 class ModuleBase_ITreeNode
 {
 public:
+  enum VisibilityState {
+    NoneState,
+    Visible,
+    SemiVisible,
+    Hidden
+  };
+
   /// Default constructor
-  ModuleBase_ITreeNode() : myParent(0) {}
+  ModuleBase_ITreeNode(ModuleBase_ITreeNode* theParent = 0) : myParent(theParent) {}
 
-  /// Returns name of the node
-  virtual QString name() const { return "Item"; }
+  virtual ~ModuleBase_ITreeNode() { deleteChildren(); }
 
-  /// Returns icon of the node
-  virtual QIcon icon() const { return QIcon(); }
+  virtual std::string type() const = 0;
 
-  /// Returns foreground color of the node
-  virtual QColor color() const { return Qt::black;  }
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const { return QVariant(); }
 
   /// Returns properties flag of the item
-  virtual Qt::ItemFlags falg() const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; }
+  virtual Qt::ItemFlags flags(int theColumn) const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; }
 
   /// Returns parent node of the current node
   ModuleBase_ITreeNode* parent() const { return myParent; }
@@ -57,10 +66,113 @@ public:
   /// Returns list of the node children
   QTreeNodesList children() const { return myChildren; }
 
+  /// Returns a children node according to given row (index)
+  ModuleBase_ITreeNode* subNode(int theRow) const
+  {
+    if ((theRow > -1) && (theRow < myChildren.length()))
+      return myChildren.at(theRow);
+    return 0;
+  }
+
+  /// Finds a node which contains the referenced object
+  /// \param theObj an object to find
+  /// \param allLevels if true then all sub-trees will be processed
+  ModuleBase_ITreeNode* subNode(const ObjectPtr& theObj, bool allLevels = true) const
+  {
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      if (aNode->object() == theObj)
+        return aNode;
+      if (allLevels) {
+        ModuleBase_ITreeNode* aSubNode = aNode->subNode(theObj, allLevels);
+        if (aSubNode)
+          return aSubNode;
+      }
+    }
+    return 0;
+  }
+
+  /// Returns true if the given node is found within children
+  /// \param theNode a node to find
+  /// \param allLevels if true then all sub-trees will be processed
+  bool hasSubNode(ModuleBase_ITreeNode* theNode, bool allLevels = true) const
+  {
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      if (aNode == theNode)
+        return true;
+      if (allLevels) {
+        if (aNode->hasSubNode(theNode))
+          return true;
+      }
+    }
+    return false;
+  }
+
+  /// Returns number of children
+  int childrenCount() const { return myChildren.length(); }
+
+  int nodeRow(ModuleBase_ITreeNode* theNode) const { return myChildren.indexOf(theNode); }
+
   /// Returns object referenced by the node (can be null)
   virtual ObjectPtr object() const { return ObjectPtr(); }
 
+  /// Updates all sub-nodes of the node (checks whole sub-tree)
+  virtual void update() {}
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects) { return QTreeNodesList(); }
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  /// \return a list of parents where nodes were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup)
+  { return QTreeNodesList(); }
+
+  /// Returns workshop object. Has to be reimplemented in a root node
+  virtual ModuleBase_IWorkshop* workshop() const { return parent()->workshop(); }
+
+  /// Returns document object of the sub-tree. Has to be reimplemented in sub-tree root object
+  virtual DocumentPtr document() const { return parent()->document(); }
+
+  /// Returns a node which belongs to the given document and contains objects of the given group
+  /// \param theDoc a document
+  /// \param theGroup a name of objects group
+  /// \return a parent node if it is found
+  virtual ModuleBase_ITreeNode* findParent(const DocumentPtr& theDoc, QString theGroup)
+  { return 0; }
+
+  /// Returns root node of a data tree of the given document
+  /// \param theDoc a document
+  /// \return a tree node which is a root of the document structure
+  virtual ModuleBase_ITreeNode* findRoot(const DocumentPtr& theDoc)
+  {
+    if (document() == theDoc)
+      return this;
+    ModuleBase_ITreeNode* aRoot;
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      aRoot = aNode->findRoot(theDoc);
+      if (aRoot)
+        return aRoot;
+    }
+    return 0;
+  }
+
+  /// Returns visibilitystate of the node in viewer 3d
+  virtual VisibilityState visibilityState() const { return NoneState; }
+
 protected:
+
+  /// deletes all children nodes (called in destructor.)
+  virtual void deleteChildren()
+  {
+    while (myChildren.size()) {
+      ModuleBase_ITreeNode* aNode = myChildren.takeLast();
+      delete aNode;
+    }
+  }
+
   ModuleBase_ITreeNode* myParent; //!< Parent of the node
   QTreeNodesList myChildren; //!< Children of the node
 };
index e9a4d2c350b788ee8249c6cc19500ec370f2bba4..e8cf8b62215e291d3aebbee535a3ebe3cf9eea22 100644 (file)
@@ -112,6 +112,10 @@ Q_OBJECT
   //! \param theAIS a presentation
   virtual ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const = 0;
 
+  //! Returns true if the object is displayed
+  //! \param theObject a data object
+  virtual bool isVisible(const ObjectPtr& theObject) const = 0;
+
   //! Select features clearing previous selection.
   //! If the list is empty then selection will be cleared
   //! \param theValues a list of presentations
index c54669495dc94918a5ad39125cc288fe312591c9..b7b72a47b2c91ad85888612732fff36771c0dc44 100755 (executable)
@@ -187,10 +187,10 @@ FeaturePtr ModuleBase_OperationFeature::createFeature(const bool theFlushMessage
      }*/
   }
 
-  if (theFlushMessage) {
-    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
-  }
+  //if (theFlushMessage) {
+  //  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+  //  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+  //}
   return myFeature;
 }
 
index 1646edc0d2bc230e17cfa35dc4001a2ed21285c2..cf141d592387a9542c9933b9c284671cb628d841 100755 (executable)
@@ -25,7 +25,7 @@
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_ResultConstruction.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeIntArray.h>
 
 #include "ModuleBase_Tools.h"
@@ -84,8 +84,8 @@ ModuleBase_ResultPrs::ModuleBase_ResultPrs(ResultPtr theResult)
     aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_PLUS, Quantity_NOC_YELLOW, 1.));
 
   // Activate individual repaintng if this is a part of compsolid
-  ResultCompSolidPtr aCompSolid = ModelAPI_Tools::compSolidOwner(myResult);
-  SetAutoHilight(aCompSolid.get() == NULL);
+  ResultBodyPtr aResOwner = ModelAPI_Tools::bodyOwner(myResult);
+  SetAutoHilight(aResOwner.get() == NULL);
 
   myHiddenSubShapesDrawer = new AIS_ColoredDrawer (myDrawer);
   Handle(Prs3d_ShadingAspect) aShadingAspect = new Prs3d_ShadingAspect();
index 73d877e8d914c6171e983f7fbeef0616412374aa..67d2b349a63673374dd92e45312bb794ffac7951 100755 (executable)
@@ -45,7 +45,6 @@
 
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Result.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultParameter.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Session.h>
@@ -680,18 +679,16 @@ bool setObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
     AttributeSelectionPtr aSelectAttr =
                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
-    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
     if (aSelectAttr.get() != NULL) {
-      aSelectAttr->setValue(aResult, theShape, theTemporarily);
+      aSelectAttr->setValue(theObject, theShape, theTemporarily);
     }
   }
   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
     AttributeSelectionListPtr aSelectionListAttr =
                          std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
-    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
     if (!theCheckIfAttributeHasObject ||
-        !aSelectionListAttr->isInList(aResult, theShape, theTemporarily))
-      aSelectionListAttr->append(aResult, theShape, theTemporarily);
+      !aSelectionListAttr->isInList(theObject, theShape, theTemporarily))
+      aSelectionListAttr->append(theObject, theShape, theTemporarily);
   }
   else if (aType == ModelAPI_AttributeRefList::typeId()) {
     AttributeRefListPtr aRefListAttr =
index d2e98f0683088ad3d016b1bec3ab4dfab6509e87..2a60ec774d664b8b78b12ca86a4eac6130dad609 100755 (executable)
@@ -836,8 +836,8 @@ bool ModuleBase_WidgetMultiSelector::removeUnusedAttributeObjects
     AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
     for (int i = 0; i < aSelectionListAttr->size(); i++) {
       AttributeSelectionPtr anAttr = aSelectionListAttr->value(i);
-      bool aFound = findInSelection(anAttr->context(), anAttr->value(), aGeomSelection,
-                                    myWorkshop);
+      bool aFound = findInSelection(
+        anAttr->contextObject(), anAttr->value(), aGeomSelection, myWorkshop);
       if (!aFound)
         anIndicesToBeRemoved.insert(i);
     }
index 3d4afc9a18ac56b24f7d825b896b20a18fa20606..9642a37afab51e5f8a0a88d82978011536c26dee 100755 (executable)
@@ -64,6 +64,8 @@ void ModuleBase_WidgetSelector::getGeomSelection(const ModuleBase_ViewerPrsPtr&
 {
   ModuleBase_ISelection* aSelection = myWorkshop->selection();
   theObject = aSelection->getResult(thePrs);
+  if (!theObject.get())
+    theObject = thePrs->object();
   theShape = aSelection->getShape(thePrs);
 }
 
index e60685b0cc5e2758cfd8b573ef25502d3aa1dc81..91713b65bdde0e49799647589065311d34c23e3b 100644 (file)
@@ -33,7 +33,7 @@
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_AttributeValidator.h>
 #include <ModelAPI_Events.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_Tools.h>
 
 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>
@@ -115,8 +115,14 @@ bool ModuleBase_WidgetValidated::isValidInFilters(const ModuleBase_ViewerPrsPtr&
       anOwner = new StdSelect_BRepOwner(aTDShape, anIO);
       myPresentedObject = aResult;
     }
-    else
-      aValid = false; // only results with a shape can be filtered
+    else {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(thePrs->object());
+      if (aFeature.get()) {
+        // Use feature as a reference to all its results
+        myPresentedObject = aFeature;
+      } else
+        aValid = false; // only results with a shape can be filtered
+    }
   }
   // checks the owner by the AIS context activated filters
   if (!anOwner.IsNull()) {
@@ -415,7 +421,7 @@ void ModuleBase_WidgetValidated::filterPresentations(QList<ModuleBase_ViewerPrsP
 //********************************************************************
 void ModuleBase_WidgetValidated::filterCompSolids(QList<ModuleBase_ViewerPrsPtr>& theValues)
 {
-  std::set<ResultCompSolidPtr> aCompSolids;
+  std::set<ResultBodyPtr> aCompSolids;
   QList<ModuleBase_ViewerPrsPtr> aValidatedValues;
 
   // Collect compsolids.
@@ -423,9 +429,9 @@ void ModuleBase_WidgetValidated::filterCompSolids(QList<ModuleBase_ViewerPrsPtr>
   for (; anIt != aLast; anIt++) {
     const ModuleBase_ViewerPrsPtr& aViewerPrs = *anIt;
     ObjectPtr anObject = aViewerPrs->object();
-    ResultCompSolidPtr aResultCompSolid =
-      std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(anObject);
-    if(aResultCompSolid.get()) {
+    ResultBodyPtr aResultCompSolid =
+      std::dynamic_pointer_cast<ModelAPI_ResultBody>(anObject);
+    if(aResultCompSolid.get() && aResultCompSolid->numberOfSubs() > 0) {
       aCompSolids.insert(aResultCompSolid);
     }
   }
@@ -436,7 +442,7 @@ void ModuleBase_WidgetValidated::filterCompSolids(QList<ModuleBase_ViewerPrsPtr>
     const ModuleBase_ViewerPrsPtr& aViewerPrs = *anIt;
     ObjectPtr anObject = aViewerPrs->object();
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
-    ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aResult);
+    ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aResult);
     if(aResCompSolidPtr.get() && (aCompSolids.find(aResCompSolidPtr) != aCompSolids.end())) {
       // Skip sub-solid of compsolid.
       continue;
index 2ed698518e31c3da57347612e08108a4ad4ae6a2..c029f0565752068615d9af7f9698f927de30a50f 100644 (file)
@@ -58,7 +58,6 @@ SET(PROJECT_HEADERS
     PartSet_WidgetSketchLabel.h
     PartSet_CenterPrs.h
     PartSet_ExternalPointsMgr.h
-       PartSet_DataModel.h
        PartSet_TreeNodes.h
 )
 
@@ -108,7 +107,6 @@ SET(PROJECT_SOURCES
     PartSet_WidgetSketchLabel.cpp
     PartSet_CenterPrs.cpp
     PartSet_ExternalPointsMgr.cpp
-       PartSet_DataModel.cpp
        PartSet_TreeNodes.cpp
 )
 
index 57f0735b537a08da50beecac64c03818b376ae79..a95e64d8bd67a7c6073fe04492fd053ecdb1b554 100644 (file)
@@ -19,6 +19,7 @@
 //
 
 #include "PartSet_DataModel.h"
+#include "PartSet_TreeNodes.h"
 
 #include <ModelAPI_Events.h>
 
 
 PartSet_DataModel::PartSet_DataModel()
 {
-  Events_Loop* aLoop = Events_Loop::loop();
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_ORDER_UPDATED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
+//  Events_Loop* aLoop = Events_Loop::loop();
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_ORDER_UPDATED));
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
 }
 
 
index c8e9292a00cb6f6323e11b134cc0f5dd68d3bb6a..99342671c2557ba5ae34287931e792af18114bb3 100755 (executable)
@@ -38,7 +38,7 @@
 #include "PartSet_CustomPrs.h"
 #include "PartSet_IconFactory.h"
 #include "PartSet_OverconstraintListener.h"
-#include "PartSet_DataModel.h"
+#include "PartSet_TreeNodes.h"
 
 #include "PartSet_Filters.h"
 #include "PartSet_FilterInfinite.h"
@@ -151,6 +151,7 @@ extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop*
 PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
 : ModuleBase_IModule(theWshop),
   myVisualLayerId(0),
+  myRoot(0),
   myIsOperationIsLaunched(false)
 {
   new PartSet_IconFactory();
@@ -158,8 +159,6 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
   mySketchMgr = new PartSet_SketcherMgr(this);
   mySketchReentrantMgr = new PartSet_SketcherReentrantMgr(theWshop);
 
-  myDataModel = new PartSet_DataModel();
-
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWshop);
   XGUI_Workshop* aWorkshop = aConnector->workshop();
 
@@ -239,8 +238,18 @@ PartSet_Module::~PartSet_Module()
   }
   delete myCustomPrs;
   delete myOverconstraintListener;
+  delete myRoot;
 }
 
+//******************************************************
+void PartSet_Module::createFeatures()
+{
+  ModuleBase_IModule::createFeatures();
+  myRoot = new PartSet_RootNode();
+  myRoot->setWorkshop(workshop());
+}
+
+
 //******************************************************
 void PartSet_Module::storeSelection()
 {
@@ -1141,10 +1150,8 @@ void PartSet_Module::onViewTransformed(int theTrsfType)
     SketcherPrs_Tools::setArrowSize(aLen);
     const double aCurScale = aViewer->activeView()->Camera()->Scale();
     aViewer->SetScale(aViewer->activeView(), aCurScale);
-    QList<AISObjectPtr> aPrsList = aDisplayer->displayedPresentations();
-    foreach (AISObjectPtr aAIS, aPrsList) {
-      Handle(AIS_InteractiveObject) aAisObj = aAIS->impl<Handle(AIS_InteractiveObject)>();
-
+    QList<Handle(AIS_InteractiveObject)> aPrsList = aDisplayer->displayedPresentations();
+    foreach(Handle(AIS_InteractiveObject) aAisObj, aPrsList) {
       Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(aAisObj);
       if (!aDim.IsNull()) {
         aDim->DimensionAspect()->ArrowAspect()->SetLength(aLen);
@@ -1663,5 +1670,5 @@ void PartSet_Module::setDefaultConstraintShown()
 //******************************************************
 ModuleBase_ITreeNode* PartSet_Module::rootNode() const
 {
-  return myDataModel->root();
+  return myRoot;
 }
index d196b6bdd392d4ccbfc823627cc95cb613af6421..3979a599bc8fa0273d067dd3b37a561fac44d009 100755 (executable)
@@ -58,7 +58,7 @@ class PartSet_MenuMgr;
 class PartSet_CustomPrs;
 class PartSet_SketcherMgr;
 class PartSet_SketcherReentrantMgr;
-class PartSet_DataModel;
+class PartSet_RootNode;
 class ModelAPI_Result;
 
 class QAction;
@@ -400,6 +400,9 @@ public:
   /// Returns the workshop
   XGUI_Workshop* getWorkshop() const;
 
+  /// Reads description of features from XML file
+  virtual void createFeatures();
+
 public slots:
   /// Slolt called on object display
   /// \param theObject a data object
@@ -495,7 +498,7 @@ private:
   PartSet_SketcherMgr::FeatureToSelectionMap myCurrentSelection;
   QModelIndex myActivePartIndex;
 
-  PartSet_DataModel* myDataModel;
+  PartSet_RootNode* myRoot;
 };
 
 #endif
index 1781e96ae3fb8d8807883b5c3b0cfbdd5fefc5ee..445c4ad8c8500baaa4f99278c7018aba828bece0 100755 (executable)
@@ -42,7 +42,7 @@
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Session.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_Tools.h>
 
 #include <Events_InfoMessage.h>
@@ -189,12 +189,12 @@ void PartSet_OperationPrs::addValue(const ObjectPtr& theObject, const GeomShapeP
   if (theObject.get()) {
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
     if (aResult.get()) {
-      ResultCompSolidPtr aCompsolidResult =
-        std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
-      if (aCompsolidResult.get()) {
-        if (aCompsolidResult->numberOfSubs() > 0) {
-          for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
-            ResultPtr aSubResult = aCompsolidResult->subResult(i);
+      ResultBodyPtr aBodyResult =
+        std::dynamic_pointer_cast<ModelAPI_ResultBody>(theObject);
+      if (aBodyResult.get()) {
+        if (aBodyResult->numberOfSubs() > 0) {
+          for(int i = 0; i < aBodyResult->numberOfSubs(); i++) {
+            ResultPtr aSubResult = aBodyResult->subResult(i);
             if (aSubResult.get()) {
               GeomShapePtr aShape;
               addValue(aSubResult, aShape, theFeature, theWorkshop, theObjectShapes);
index 7e62e4b9fb559cd2df26c16b49a6bb450d98a0bf..eec581b6729d57940fa1b29246b8983f4be87b2a 100755 (executable)
@@ -25,7 +25,7 @@
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_ResultConstruction.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <GeomAPI_PlanarEdges.h>
 
 #include <Events_InfoMessage.h>
@@ -74,8 +74,8 @@ PartSet_ResultSketchPrs::PartSet_ResultSketchPrs(ResultPtr theResult)
     aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_PLUS, Quantity_NOC_YELLOW, 1.));
 
   // Activate individual repaintng if this is a part of compsolid
-  ResultCompSolidPtr aCompSolid = ModelAPI_Tools::compSolidOwner(myResult);
-  SetAutoHilight(aCompSolid.get() == NULL);
+  ResultBodyPtr anOwner = ModelAPI_Tools::bodyOwner(myResult);
+  SetAutoHilight(anOwner.get() == NULL);
 
   ModuleBase_Tools::setPointBallHighlighting(this);
 }
index 3d029e57b61da1390b7847ed46264f9d46576a77..5e642c691aba56927ddd26dbe083d0db2579e517 100644 (file)
 
 #include "PartSet_TreeNodes.h"
 
+#include <ModuleBase_IconFactory.h>
+#include <ModuleBase_IWorkshop.h>
 
-PartSet_RootNode::PartSet_RootNode()
+#include <PartSetPlugin_Part.h>
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_ResultParameter.h>
+#include <ModelAPI_ResultField.h>
+#include <ModelAPI_ResultGroup.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_CompositeFeature.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_Folder.h>
+#include <ModelAPI_AttributeReference.h>
+
+#include <QBrush>
+#include <QMap>
+
+
+#define ACTIVE_COLOR QColor(Qt::black)
+#define SELECTABLE_COLOR QColor(100, 100, 100)
+#define DISABLED_COLOR QColor(200, 200, 200)
+
+Qt::ItemFlags aNullFlag;
+Qt::ItemFlags aDefaultFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+Qt::ItemFlags aEditingFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
+
+
+ResultPartPtr getPartResult(const ObjectPtr& theObj)
+{
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+  if (aFeature) {
+    ResultPtr aRes = aFeature->firstResult();
+    if (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group())) {
+      ResultPartPtr aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aRes);
+      // Use only original parts, not a placement results
+      if (aPartRes == aPartRes->original())
+        return aPartRes;
+    }
+  }
+  return ResultPartPtr();
+}
+
+bool isCurrentFeature(const ObjectPtr& theObj)
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aCurDoc = aSession->activeDocument();
+  FeaturePtr aFeature = aCurDoc->currentFeature(true);
+  return aFeature == theObj;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+QVariant PartSet_TreeNode::data(int theColumn, int theRole) const
+{
+  if ((theColumn == 1) && (theRole == Qt::ForegroundRole)) {
+    Qt::ItemFlags aFlags = flags(theColumn);
+    if (aFlags == Qt::ItemFlags())
+      return QBrush(DISABLED_COLOR);
+    if (!aFlags.testFlag(Qt::ItemIsEditable))
+      return QBrush(SELECTABLE_COLOR);
+    return ACTIVE_COLOR;
+  }
+  return ModuleBase_ITreeNode::data(theColumn, theRole);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+QVariant PartSet_ObjectNode::data(int theColumn, int theRole) const
+{
+  switch (theRole) {
+  case Qt::DisplayRole:
+    if (theColumn == 1) {
+      if (myObject->groupName() == ModelAPI_ResultParameter::group()) {
+        ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(myObject);
+        AttributeDoublePtr aValueAttribute =
+          aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+        QString aVal = QString::number(aValueAttribute->value());
+        QString aTitle = QString(myObject->data()->name().c_str());
+        return aTitle + " = " + aVal;
+      }
+      return myObject->data()->name().c_str();
+    }
+    break;
+  case Qt::DecorationRole:
+    switch (theColumn) {
+    case 0:
+      switch (visibilityState()) {
+      case NoneState:
+        return QIcon();
+      case Visible:
+        return QIcon(":pictures/eyeopen.png");
+      case SemiVisible:
+        return QIcon(":pictures/eyemiclosed.png");
+      case Hidden:
+        return QIcon(":pictures/eyeclosed.png");
+      }
+    case 1:
+      if (myObject->groupName() == ModelAPI_Folder::group())
+        return QIcon(":pictures/features_folder.png");
+      else
+        return ModuleBase_IconFactory::get()->getIcon(myObject);
+    case 2:
+      if (isCurrentFeature(myObject))
+        return QIcon(":pictures/arrow.png");
+    }
+  }
+  return PartSet_TreeNode::data(theColumn, theRole);
+}
+
+Qt::ItemFlags PartSet_ObjectNode::flags(int theColumn) const
 {
+  if (myObject->isDisabled()) {
+    return (theColumn == 2) ? Qt::ItemIsSelectable : aNullFlag;
+  } else {
+    DocumentPtr aDoc = myObject->document();
+    SessionPtr aSession = ModelAPI_Session::get();
+    if (aSession->activeDocument() == aDoc)
+      return aEditingFlag;
+  }
+  return aDefaultFlag;
+}
+
+PartSet_ObjectNode::VisibilityState PartSet_ObjectNode::visibilityState() const
+{
+  Qt::ItemFlags aFlags = flags(1);
+  if (aFlags == Qt::ItemFlags())
+    return NoneState;
+
+  if (myObject->groupName() == ModelAPI_ResultParameter::group())
+    return NoneState;
+  ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
+  if (aResObj.get()) {
+    ModuleBase_IWorkshop* aWork = workshop();
+    ResultBodyPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResObj);
+    if (aCompRes.get()) {
+      VisibilityState aState = aCompRes->numberOfSubs(true) == 0 ?
+        (aWork->isVisible(aCompRes) ? Visible : Hidden) : NoneState;
+      std::list<ResultPtr> aResultsList;
+      ModelAPI_Tools::allSubs(aCompRes, aResultsList);
+
+      std::list<ResultPtr>::const_iterator aIt;
+      //for (int i = 0; i < aCompRes->numberOfSubs(true); i++) {
+      for (aIt = aResultsList.cbegin(); aIt != aResultsList.cend(); aIt++) {
+        ResultPtr aSubRes = (*aIt); // aCompRes->subResult(i, true);
+        VisibilityState aS = aWork->isVisible(aSubRes) ? Visible : Hidden;
+        if (aState == NoneState)
+          aState = aS;
+        else if (aState != aS) {
+          aState = SemiVisible;
+          break;
+        }
+      }
+      return aState;
+    } else {
+      if (aWork->isVisible(aResObj))
+        return Visible;
+      else
+        return Hidden;
+    }
+  }
+  return NoneState;
+}
+
+void PartSet_ObjectNode::update()
+{
+  ResultBodyPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myObject);
+  if (aCompRes.get()) {
+    int aNb = aCompRes->numberOfSubs(true);
+    ModuleBase_ITreeNode* aNode;
+    ResultBodyPtr aBody;
+    int i;
+    for (i = 0; i < aNb; i++) {
+      aBody = aCompRes->subResult(i, true);
+      if (i < myChildren.size()) {
+        aNode = myChildren.at(i);
+        if (aNode->object() != aBody) {
+          ((PartSet_ObjectNode*)aNode)->setObject(aBody);
+        }
+      } else {
+        aNode = new PartSet_ObjectNode(aBody, this);
+        myChildren.append(aNode);
+      }
+    }
+    // Delete extra objects
+    while (myChildren.size() > aNb) {
+      aNode = myChildren.takeLast();
+      delete aNode;
+    }
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      aNode->update();
+    }
+  }
+}
+
+QTreeNodesList PartSet_ObjectNode::objectCreated(const QObjectPtrList& theObjects)
+{
+  QTreeNodesList aResult;
+
+  ResultBodyPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myObject);
+  if (aCompRes.get()) {
+    int aNb = aCompRes->numberOfSubs(true);
+    ModuleBase_ITreeNode* aNode;
+    ResultBodyPtr aBody;
+    int i;
+    for (i = 0; i < aNb; i++) {
+      aBody = aCompRes->subResult(i, true);
+      if (i < myChildren.size()) {
+        aNode = myChildren.at(i);
+        if (aNode->object() != aBody) {
+          ((PartSet_ObjectNode*)aNode)->setObject(aBody);
+          aResult.append(aNode);
+        }
+      } else {
+        aNode = new PartSet_ObjectNode(aBody, this);
+        myChildren.append(aNode);
+        aResult.append(aNode);
+      }
+    }
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      aResult.append(aNode->objectCreated(theObjects));
+    }
+  }
+  return aResult;
+}
+
+QTreeNodesList PartSet_ObjectNode::objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup)
+{
+  QTreeNodesList aResult;
+  ResultBodyPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myObject);
+  if (aCompRes.get()) {
+    int aNb = aCompRes->numberOfSubs(true);
+    ModuleBase_ITreeNode* aNode;
+    // Delete extra objects
+    bool isDeleted = false;
+    while (myChildren.size() > aNb) {
+      aNode = myChildren.takeLast();
+      delete aNode;
+      isDeleted = true;
+    }
+    if (isDeleted)
+      aResult.append(this);
+    int i = 0;
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      ((PartSet_ObjectNode*)aNode)->setObject(aCompRes->subResult(i, true));
+      aResult.append(aNode->objectsDeleted(theDoc, theGroup));
+      i++;
+    }
+  }
+  return aResult;
+}
+//////////////////////////////////////////////////////////////////////////////////
+PartSet_FolderNode::PartSet_FolderNode(ModuleBase_ITreeNode* theParent,
+  FolderType theType)
+  : PartSet_TreeNode(theParent), myType(theType)
+{
+}
+
+QString PartSet_FolderNode::name() const
+{
+  switch (myType) {
+  case ParametersFolder:
+    return QObject::tr("Parameters");
+  case ConstructionFolder:
+    return QObject::tr("Constructions");
+  case PartsFolder:
+    return QObject::tr("Parts");
+  case ResultsFolder:
+    return QObject::tr("Results");
+  case FieldsFolder:
+    return QObject::tr("Fields");
+  case GroupsFolder:
+    return QObject::tr("Groups");
+  }
+  return "NoName";
+}
+
+
+QVariant PartSet_FolderNode::data(int theColumn, int theRole) const
+{
+  static QIcon aParamsIco(":pictures/params_folder.png");
+  static QIcon aConstrIco(":pictures/constr_folder.png");
+
+  if (theColumn == 1) {
+    switch (theRole) {
+    case Qt::DisplayRole:
+      return name() + QString(" (%1)").arg(childrenCount());
+    case Qt::DecorationRole:
+      switch (myType) {
+      case ParametersFolder:
+        return aParamsIco;
+      case ConstructionFolder:
+        return aConstrIco;
+      case PartsFolder:
+        return aConstrIco;
+      case ResultsFolder:
+        return aConstrIco;
+      case FieldsFolder:
+        return aConstrIco;
+      case GroupsFolder:
+        return aConstrIco;
+      }
+    }
+  }
+  return PartSet_TreeNode::data(theColumn, theRole);
+}
+
+Qt::ItemFlags PartSet_FolderNode::flags(int theColumn) const
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aActiveDoc = aSession->activeDocument();
+  if (theColumn == 1) {
+    if (document() == aActiveDoc)
+      return aEditingFlag;
+  }
+  return aDefaultFlag;
+}
+
+ModuleBase_ITreeNode* PartSet_FolderNode::createNode(const ObjectPtr& theObj)
+{
+  //ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObj);
+  //if (aCompRes.get())
+  //  return new PartSet_CompsolidNode(theObj, this);
+  return new PartSet_ObjectNode(theObj, this);
+}
+
+void PartSet_FolderNode::update()
+{
+  DocumentPtr aDoc = document();
+  if (!aDoc.get())
+    return;
+
+  // Remove extra sub-nodes
+  int aIndex;
+  int aId = 0;
+  while (aId < myChildren.size()) {
+    ModuleBase_ITreeNode* aNode = myChildren.at(aId);
+    aIndex = aDoc->index(aNode->object(), true);
+    if ((aIndex == -1) || (aId != aIndex)) {
+      myChildren.removeAll(aNode);
+      delete aNode;
+    } else
+      aId++;
+  }
+
+  // Add new nodes
+  std::string aGroup = groupName();
+  int aSize = aDoc->size(aGroup, true);
+  for (int i = 0; i < aSize; i++) {
+    ObjectPtr aObj = aDoc->object(aGroup, i, true);
+    if (i < myChildren.size()) {
+      if (myChildren.at(i)->object() != aObj) {
+        ModuleBase_ITreeNode* aNode = createNode(aObj);
+        myChildren.insert(i, aNode);
+      }
+    } else {
+      ModuleBase_ITreeNode* aNode = createNode(aObj);
+      myChildren.append(aNode);
+    }
+  }
+
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    aNode->update();
+  }
+}
+
+std::string PartSet_FolderNode::groupName() const
+{
+  switch (myType) {
+  case ParametersFolder:
+    return ModelAPI_ResultParameter::group();
+  case ConstructionFolder:
+    return ModelAPI_ResultConstruction::group();
+  case PartsFolder:
+    return ModelAPI_ResultPart::group();
+  case ResultsFolder:
+    return ModelAPI_ResultBody::group();
+  case FieldsFolder:
+    return ModelAPI_ResultField::group();
+  case GroupsFolder:
+    return ModelAPI_ResultGroup::group();
+  }
+  return "";
+}
+
+QTreeNodesList PartSet_FolderNode::objectCreated(const QObjectPtrList& theObjects)
+{
+  QTreeNodesList aResult;
+  std::string aName = groupName();
+  DocumentPtr aDoc = document();
+  int aIdx = -1;
+  QMap<int, ModuleBase_ITreeNode*> aNewNodes;
+  foreach(ObjectPtr aObj, theObjects) {
+    if ((aObj->document() == aDoc) && (aObj->groupName() == aName)) {
+      aIdx = aDoc->index(aObj, true);
+      if (aIdx != -1) {
+        bool aHasObject = (aIdx < myChildren.size()) && (myChildren.at(aIdx)->object() == aObj);
+        if (!aHasObject) {
+          ModuleBase_ITreeNode* aNode = createNode(aObj);
+          aNewNodes[aIdx] = aNode;
+          aResult.append(aNode);
+        }
+      }
+    }
+  }
+  // Add nodes in correct order
+  int i;
+  for (i = 0; i < myChildren.size(); i++) {
+    if (aNewNodes.contains(i)) {
+      myChildren.insert(i, aNewNodes[i]);
+      aNewNodes.remove(i);
+    }
+  }
+  while (aNewNodes.size()) {
+    i = myChildren.size();
+    myChildren.append(aNewNodes[i]);
+    aNewNodes.remove(i);
+  }
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    aResult.append(aNode->objectCreated(theObjects));
+  }
+  return aResult;
+}
+
+QTreeNodesList PartSet_FolderNode::objectsDeleted(const DocumentPtr& theDoc,
+  const QString& theGroup)
+{
+  DocumentPtr aDoc = document();
+  QTreeNodesList aResult;
+  if ((theGroup.toStdString() == groupName()) && (theDoc == aDoc)) {
+    QTreeNodesList aDelList;
+    int aIndex;
+    int aId = 0;
+    bool aRemoved = false;
+    while (aId < myChildren.size()) {
+      ModuleBase_ITreeNode* aNode = myChildren.at(aId);
+      aIndex = aDoc->index(aNode->object(), true);
+      if ((aIndex == -1) || (aId != aIndex)) {
+        myChildren.removeAll(aNode);
+        delete aNode;
+        aRemoved = true;
+      }  else
+        aId++;
+    }
+    if (aRemoved)
+      aResult.append(this);
+
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      aResult.append(aNode->objectsDeleted(theDoc, theGroup));
+    }
+  }
+  return aResult;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+QTreeNodesList PartSet_FeatureFolderNode::objectCreated(const QObjectPtrList& theObjects)
+{
+  QTreeNodesList aResult;
+  // Process all folders
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    if (aNode->type() == PartSet_FolderNode::typeId()) { // aFolder node
+      aResult.append(aNode->objectCreated(theObjects));
+    }
+  }
+  // Process the root sub-objects
+  DocumentPtr aDoc = document();
+  int aIdx = -1;
+  int aNb = numberOfFolders();
+  QMap<int, ModuleBase_ITreeNode*> aNewNodes;
+  foreach(ObjectPtr aObj, theObjects) {
+    if (aDoc == aObj->document()) {
+      if ((aObj->groupName() == ModelAPI_Feature::group()) ||
+        (aObj->groupName() == ModelAPI_Folder::group())){
+        ModuleBase_ITreeNode* aNode = createNode(aObj);
+        aIdx = aDoc->index(aObj, true);
+        if (aIdx != -1) {
+          aIdx += aNb;
+          bool aHasObject = (aIdx < myChildren.size()) && (myChildren.at(aIdx)->object() == aObj);
+          if (!aHasObject) {
+            aNewNodes[aIdx] = aNode;
+            aResult.append(aNode);
+          }
+        }
+      }
+    }
+  }
+  // To add in correct order
+  int i;
+  for (i = 0; i < myChildren.size(); i++) {
+    if (aNewNodes.contains(i)) {
+      myChildren.insert(i, aNewNodes[i]);
+      aNewNodes.remove(i);
+    }
+  }
+  while (aNewNodes.size()) {
+    i = myChildren.size();
+    myChildren.append(aNewNodes[i]);
+    aNewNodes.remove(i);
+  }
+
+  // Update sub-folders
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    if ((aNode->type() == PartSet_ObjectFolderNode::typeId()) ||
+      (aNode->type() == PartSet_PartRootNode::typeId()))
+      aResult.append(aNode->objectCreated(theObjects));
+  }
+  return aResult;
+}
+
+QTreeNodesList PartSet_FeatureFolderNode::objectsDeleted(const DocumentPtr& theDoc,
+  const QString& theGroup)
+{
+  QTreeNodesList aResult;
+
+  // Process sub-folders
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    if (aNode->childrenCount() > 0) { // aFolder node
+      QTreeNodesList aList = aNode->objectsDeleted(theDoc, theGroup);
+      if (aList.size() > 0)
+        aResult.append(aList);
+    }
+  }
+
+  // Process root
+  DocumentPtr aDoc = document();
+  int aNb = numberOfFolders();
+  bool isGroup = ((theGroup.toStdString() == ModelAPI_Feature::group()) ||
+    (theGroup.toStdString() == ModelAPI_Folder::group()));
+  if ((theDoc == aDoc) && isGroup) {
+    int aIndex;
+    int aId = 0;
+    bool aRemoved = false;
+    while (aId < myChildren.size()) {
+      ModuleBase_ITreeNode* aNode = myChildren.at(aId);
+      if (aNode->object().get()) {
+        aIndex = aDoc->index(aNode->object(), true);
+        if ((aIndex == -1) || (aId != (aIndex + aNb))) {
+          myChildren.removeAll(aNode);
+          delete aNode;
+          aRemoved = true;
+          continue;
+        }
+      }
+      aId++;
+    }
+    if (aRemoved)
+      aResult.append(this);
+  }
+  return aResult;
+}
+
+ModuleBase_ITreeNode* PartSet_FeatureFolderNode::findParent(const DocumentPtr& theDoc,
+  QString theGroup)
+{
+  ModuleBase_ITreeNode* aResult = 0;
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    aResult = aNode->findParent(theDoc, theGroup);
+    if (aResult) {
+      return aResult;
+    }
+  }
+  bool isGroup = ((theGroup.toStdString() == ModelAPI_Feature::group()) ||
+    (theGroup.toStdString() == ModelAPI_Folder::group()));
+  if ((theDoc == document()) && isGroup)
+    return this;
+  return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+PartSet_RootNode::PartSet_RootNode() : PartSet_FeatureFolderNode(0), myWorkshop(0)
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aDoc = aSession->moduleDocument();
+
+  myParamsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ParametersFolder);
+  myConstrFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ConstructionFolder);
+  myPartsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::PartsFolder);
 
-}
\ No newline at end of file
+  myChildren.append(myParamsFolder);
+  myChildren.append(myConstrFolder);
+  myChildren.append(myPartsFolder);
+
+  update();
+}
+
+
+void PartSet_RootNode::update()
+{
+  myParamsFolder->update();
+  myConstrFolder->update();
+  myPartsFolder->update();
+
+  // Update features content
+  DocumentPtr aDoc = document();
+  int aNb = numberOfFolders();
+
+  // Remove extra sub-nodes
+  int aIndex;
+  int aId = 0;
+  while (aId < myChildren.size()) {
+    ModuleBase_ITreeNode* aNode = myChildren.at(aId);
+    if (aNode->object().get()) {
+      aIndex = aDoc->index(aNode->object(), true);
+      if ((aIndex == -1) || (aId != (aIndex + aNb))) {
+        myChildren.removeAll(aNode);
+        delete aNode;
+        continue;
+      }
+    }
+    aId++;
+  }
+
+  // Add new nodes
+  std::string aGroup = ModelAPI_Feature::group();
+  int aSize = aDoc->size(aGroup, true);
+  FeaturePtr aFeature;
+  for (int i = 0; i < aSize; i++) {
+    ObjectPtr aObj = aDoc->object(aGroup, i, true);
+    aId = i + aNb; // Take into account existing folders
+    if (aId < myChildren.size()) {
+      if (myChildren.at(aId)->object() != aObj) {
+        ModuleBase_ITreeNode* aNode = createNode(aObj);
+        myChildren.insert(aId, aNode);
+      }
+    } else {
+      ModuleBase_ITreeNode* aNode = createNode(aObj);
+      myChildren.append(aNode);
+    }
+  }
+  // Update sub-folders
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    if ((aNode->type() == PartSet_ObjectFolderNode::typeId()) ||
+      (aNode->type() == PartSet_PartRootNode::typeId()))
+      aNode->update();
+  }
+}
+
+DocumentPtr PartSet_RootNode::document() const
+{
+  return ModelAPI_Session::get()->moduleDocument();
+}
+
+ModuleBase_ITreeNode* PartSet_RootNode::createNode(const ObjectPtr& theObj)
+{
+  if (theObj->groupName() == ModelAPI_Folder::group())
+    return new PartSet_ObjectFolderNode(theObj, this);
+
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+  if (aFeature->getKind() == PartSetPlugin_Part::ID())
+    return new PartSet_PartRootNode(theObj, this);
+
+  return new PartSet_ObjectNode(theObj, this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+PartSet_PartRootNode::PartSet_PartRootNode(const ObjectPtr& theObj, ModuleBase_ITreeNode* theParent)
+  : PartSet_FeatureFolderNode(theParent), myObject(theObj)
+{
+  myParamsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ParametersFolder);
+  myConstrFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ConstructionFolder);
+  myResultsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ResultsFolder);
+  myFieldsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::FieldsFolder);
+  myGroupsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::GroupsFolder);
+
+  myChildren.append(myParamsFolder);
+  myChildren.append(myConstrFolder);
+  myChildren.append(myResultsFolder);
+
+  update();
+}
+
+void PartSet_PartRootNode::deleteChildren()
+{
+  if (!myFieldsFolder->childrenCount()) {
+    delete myFieldsFolder;
+  }
+  if (!myGroupsFolder->childrenCount()) {
+    delete myGroupsFolder;
+  }
+  PartSet_FeatureFolderNode::deleteChildren();
+}
+
+
+void PartSet_PartRootNode::update()
+{
+  DocumentPtr aDoc = document();
+  if (!aDoc.get())
+    return;
+
+  myParamsFolder->update();
+  myConstrFolder->update();
+  myResultsFolder->update();
+  myFieldsFolder->update();
+  myGroupsFolder->update();
+
+  bool aHasFields = myFieldsFolder->childrenCount() > 0;
+  bool aHasGroups = myGroupsFolder->childrenCount() > 0;
+  if (aHasFields && (!myChildren.contains(myFieldsFolder))) {
+    myChildren.insert(3, myFieldsFolder);
+  }
+  if (aHasGroups && (!myChildren.contains(myGroupsFolder))) {
+    myChildren.insert(aHasFields ? 4 : 3, myGroupsFolder);
+  }
+
+  // Update features content
+  int aRows = numberOfFolders();
+
+  // Remove extra sub-nodes
+  int aIndex = -1;
+  int aId = 0;
+  while (aId < myChildren.size()) {
+    ModuleBase_ITreeNode* aNode = myChildren.at(aId);
+    if (aNode->object().get()) {
+      aIndex = aDoc->index(aNode->object(), true);
+      if ((aIndex == -1) || (aId != (aIndex + aRows))) {
+        myChildren.removeAll(aNode);
+        delete aNode;
+        continue;
+      }
+    }
+    aId++;
+  }
+
+  std::string aGroup = ModelAPI_Feature::group();
+  int aSize = aDoc->size(aGroup, true);
+  FeaturePtr aFeature;
+  for (int i = 0; i < aSize; i++) {
+    ObjectPtr aObj = aDoc->object(aGroup, i, true);
+    aId = i + aRows; // Take into account existing folders
+    if (aId < myChildren.size()) {
+      if (myChildren.at(aId)->object() != aObj) {
+        ModuleBase_ITreeNode* aNode = createNode(aObj);
+        myChildren.insert(aId, aNode);
+      }
+    } else {
+      ModuleBase_ITreeNode* aNode = createNode(aObj);
+      myChildren.append(aNode);
+    }
+  }
+  // Update sub-folders
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    if (aNode->type() == PartSet_ObjectFolderNode::typeId())
+      aNode->update();
+  }
+}
+
+DocumentPtr PartSet_PartRootNode::document() const
+{
+  ResultPartPtr aPartRes = getPartResult(myObject);
+  if (aPartRes.get())
+    return aPartRes->partDoc();
+  return DocumentPtr();
+}
+
+QVariant PartSet_PartRootNode::data(int theColumn, int theRole) const
+{
+  switch (theColumn) {
+  case 1:
+    switch (theRole) {
+    case Qt::DisplayRole:
+      return QString(myObject->data()->name().c_str());
+    case Qt::DecorationRole:
+      return ModuleBase_IconFactory::get()->getIcon(myObject);
+    }
+  case 2:
+    if (theRole == Qt::DecorationRole)
+      if (isCurrentFeature(myObject))
+        return QIcon(":pictures/arrow.png");
+  }
+  return PartSet_TreeNode::data(theColumn, theRole);
+}
+
+Qt::ItemFlags PartSet_PartRootNode::flags(int theColumn) const
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aActiveDoc = aSession->activeDocument();
+  if ((aActiveDoc == document()) || (myObject->document() == aActiveDoc))
+    return aEditingFlag;
+  return aDefaultFlag;
+}
+
+ModuleBase_ITreeNode* PartSet_PartRootNode::createNode(const ObjectPtr& theObj)
+{
+  if (theObj->groupName() == ModelAPI_Folder::group())
+    return new PartSet_ObjectFolderNode(theObj, this);
+  return new PartSet_ObjectNode(theObj, this);
+}
+
+int PartSet_PartRootNode::numberOfFolders() const
+{
+  int aNb = 3;
+  if (myFieldsFolder->childrenCount() > 0)
+    aNb++;
+  if (myGroupsFolder->childrenCount() > 0)
+    aNb++;
+  return aNb;
+}
+
+QTreeNodesList PartSet_PartRootNode::objectCreated(const QObjectPtrList& theObjects)
+{
+  QTreeNodesList aResult = PartSet_FeatureFolderNode::objectCreated(theObjects);
+  if (!myFieldsFolder->childrenCount()) {
+    QTreeNodesList aList = myFieldsFolder->objectCreated(theObjects);
+    if (aList.size()) {
+      myChildren.insert(3, myFieldsFolder);
+      aResult.append(myFieldsFolder);
+      aResult.append(aList);
+    }
+  }
+  if (!myGroupsFolder->childrenCount()) {
+    QTreeNodesList aList = myGroupsFolder->objectCreated(theObjects);
+    if (aList.size()) {
+      myChildren.insert(myFieldsFolder->childrenCount()? 4 : 3, myGroupsFolder);
+      aResult.append(myGroupsFolder);
+      aResult.append(aList);
+    }
+  }
+  return aResult;
+}
+
+QTreeNodesList PartSet_PartRootNode::objectsDeleted(const DocumentPtr& theDoc,
+  const QString& theGroup)
+{
+  QTreeNodesList aResult;
+  if (myFieldsFolder->childrenCount()) {
+    QTreeNodesList aList = myFieldsFolder->objectsDeleted(theDoc, theGroup);
+    if (aList.size()) {
+      aResult.append(aList);
+      if (!myFieldsFolder->childrenCount())
+        myChildren.removeAll(myFieldsFolder);
+    }
+  }
+  if (myGroupsFolder->childrenCount()) {
+    QTreeNodesList aList = myGroupsFolder->objectsDeleted(theDoc, theGroup);
+    if (aList.size()) {
+      aResult.append(aList);
+      if (!myGroupsFolder->childrenCount())
+        myChildren.removeAll(myGroupsFolder);
+    }
+  }
+  aResult.append(PartSet_FeatureFolderNode::objectsDeleted(theDoc, theGroup));
+  return aResult;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+void PartSet_ObjectFolderNode::update()
+{
+  int aFirst, aLast;
+  getFirstAndLastIndex(aFirst, aLast);
+  if ((aFirst == -1) || (aLast == -1)) {
+    deleteChildren();
+    return;
+  }
+
+  int aNbItems = aLast - aFirst + 1;
+  if (!aNbItems) {
+    deleteChildren();
+    return;
+  }
+
+  DocumentPtr aDoc = myObject->document();
+  // Delete obsolete nodes
+  int aId = 0;
+  while (aId < myChildren.size()) {
+    ModuleBase_ITreeNode* aNode = myChildren.at(aId);
+    if ((aFirst + aId) < aDoc->size(ModelAPI_Feature::group(), true)) {
+      if (aNode->object() != aDoc->object(ModelAPI_Feature::group(), aFirst + aId)) {
+        myChildren.removeAll(aNode);
+        delete aNode;
+        continue;
+      }
+    }
+    aId++;
+  }
+
+  // Add new nodes
+  ModuleBase_ITreeNode* aNode;
+  for (int i = 0; i < aNbItems; i++) {
+    ObjectPtr aObj = aDoc->object(ModelAPI_Feature::group(), aFirst + i);
+    if (i < myChildren.size()) {
+      if (aObj != myChildren.at(i)->object()) {
+        aNode = new PartSet_ObjectNode(aObj, this);
+        myChildren.insert(i, aNode);
+      }
+    } else {
+      aNode = new PartSet_ObjectNode(aObj, this);
+      myChildren.append(aNode);
+    }
+  }
+}
+
+QTreeNodesList PartSet_ObjectFolderNode::objectCreated(const QObjectPtrList& theObjects)
+{
+  QTreeNodesList aResult;
+  int aFirst, aLast;
+  getFirstAndLastIndex(aFirst, aLast);
+  if ((aFirst == -1) || (aLast == -1)) {
+    return aResult;
+  }
+  int aNbItems = aLast - aFirst + 1;
+  if (!aNbItems) {
+    return aResult;
+  }
+  DocumentPtr aDoc = myObject->document();
+  // Add new nodes
+  ModuleBase_ITreeNode* aNode;
+  for (int i = 0; i < aNbItems; i++) {
+    ObjectPtr aObj = aDoc->object(ModelAPI_Feature::group(), aFirst + i);
+    if (i < myChildren.size()) {
+      if (aObj != myChildren.at(i)->object()) {
+        aNode = new PartSet_ObjectNode(aObj, this);
+        myChildren.insert(i, aNode);
+        aResult.append(aNode);
+      }
+    } else {
+      aNode = new PartSet_ObjectNode(aObj, this);
+      myChildren.append(aNode);
+      aResult.append(aNode);
+    }
+  }
+  return aResult;
+}
+
+QTreeNodesList PartSet_ObjectFolderNode::objectsDeleted(const DocumentPtr& theDoc,
+  const QString& theGroup)
+{
+  QTreeNodesList aResult;
+  int aFirst, aLast;
+  getFirstAndLastIndex(aFirst, aLast);
+  if ((aFirst == -1) || (aLast == -1)) {
+    return aResult;
+  }
+  int aNbItems = aLast - aFirst + 1;
+  if (!aNbItems) {
+    return aResult;
+  }
+  DocumentPtr aDoc = myObject->document();
+  // Delete obsolete nodes
+  bool aRemoved = false;
+  int aId = 0;
+  while (aId < myChildren.size()) {
+    ModuleBase_ITreeNode* aNode = myChildren.at(aId);
+    if ((aFirst + aId) < aDoc->size(ModelAPI_Feature::group(), true)) {
+      if (aNode->object() != aDoc->object(ModelAPI_Feature::group(), aFirst + aId)) {
+        myChildren.removeAll(aNode);
+        delete aNode;
+        aRemoved = true;
+        continue;
+      }
+    }
+    aId++;
+  }
+  if (aRemoved) {
+    aResult.append(this);
+  }
+  return aResult;
+}
+
+FeaturePtr PartSet_ObjectFolderNode::getFeature(const std::string& theId) const
+{
+  FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(myObject);
+  AttributeReferencePtr aFeatAttr = aFolder->data()->reference(theId);
+  if (aFeatAttr)
+    return ModelAPI_Feature::feature(aFeatAttr->value());
+  return FeaturePtr();
+}
+
+void PartSet_ObjectFolderNode::getFirstAndLastIndex(int& theFirst, int& theLast) const
+{
+  DocumentPtr aDoc = myObject->document();
+  FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(myObject);
+
+  FeaturePtr aFirstFeatureInFolder = getFeature(ModelAPI_Folder::FIRST_FEATURE_ID());
+  if (!aFirstFeatureInFolder.get()) {
+    theFirst = -1;
+    return;
+  }
+  FeaturePtr aLastFeatureInFolder = getFeature(ModelAPI_Folder::LAST_FEATURE_ID());
+  if (!aLastFeatureInFolder.get()) {
+    theLast = -1;
+    return;
+  }
+
+  theFirst = aDoc->index(aFirstFeatureInFolder);
+  theLast = aDoc->index(aLastFeatureInFolder);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+//PartSet_CompsolidNode::PartSet_CompsolidNode(const ObjectPtr& theObj,
+//  ModuleBase_ITreeNode* theParent) : PartSet_ObjectNode(theObj, theParent)
+//{
+//  update();
+//}
+
+//void PartSet_CompsolidNode::update()
+//{
+//  ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(myObject);
+//  int aNb = aCompRes->numberOfSubs(true);
+//  ModuleBase_ITreeNode* aNode;
+//  ResultBodyPtr aBody;
+//  int i;
+//  for (i = 0; i < aNb; i++) {
+//    aBody = aCompRes->subResult(i, true);
+//    if (i < myChildren.size()) {
+//      aNode = myChildren.at(i);
+//      if (aNode->object() != aBody) {
+//        ((PartSet_ObjectNode*)aNode)->setObject(aBody);
+//      }
+//    } else {
+//      aNode = new PartSet_ObjectNode(aBody, this);
+//      myChildren.append(aNode);
+//    }
+//  }
+//  // Delete extra objects
+//  while (myChildren.size() > aNb) {
+//    aNode = myChildren.takeLast();
+//    delete aNode;
+//  }
+//}
+//
+//QTreeNodesList PartSet_CompsolidNode::objectCreated(const QObjectPtrList& theObjects)
+//{
+//  QTreeNodesList aResult;
+//
+//  ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(myObject);
+//  int aNb = aCompRes->numberOfSubs(true);
+//  ModuleBase_ITreeNode* aNode;
+//  ResultBodyPtr aBody;
+//  int i;
+//  for (i = 0; i < aNb; i++) {
+//    aBody = aCompRes->subResult(i, true);
+//    if (i < myChildren.size()) {
+//      aNode = myChildren.at(i);
+//      if (aNode->object() != aBody) {
+//        ((PartSet_ObjectNode*)aNode)->setObject(aBody);
+//        aResult.append(aNode);
+//      }
+//    } else {
+//      aNode = new PartSet_ObjectNode(aBody, this);
+//      myChildren.append(aNode);
+//      aResult.append(aNode);
+//    }
+//  }
+//  return aResult;
+//}
+//
+//QTreeNodesList PartSet_CompsolidNode::objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup)
+//{
+//  QTreeNodesList aResult;
+//  ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(myObject);
+//  int aNb = aCompRes->numberOfSubs(true);
+//  ModuleBase_ITreeNode* aNode;
+//  // Delete extra objects
+//  bool isDeleted = false;
+//  while (myChildren.size() > aNb) {
+//    aNode = myChildren.takeLast();
+//    delete aNode;
+//    isDeleted = true;
+//  }
+//  if (isDeleted)
+//    aResult.append(this);
+//  return aResult;
+//}
\ No newline at end of file
index 6c165b1981581a93231dddc719b553b9b2f73dd5..8a78317eac626aa37308f876ca2f3fd074eb01c7 100644 (file)
 #include "PartSet.h"
 
 #include <ModuleBase_ITreeNode.h>
+#include <ModelAPI_Feature.h>
 
-class PartSet_RootNode : public ModuleBase_ITreeNode
+
+/**
+* \ingroup Modules
+* Implementation of base node for the module data tree
+*/
+class PartSet_TreeNode : public ModuleBase_ITreeNode
+{
+public:
+  PartSet_TreeNode(ModuleBase_ITreeNode* theParent = 0) : ModuleBase_ITreeNode(theParent) {}
+
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const;
+};
+
+/**
+* \ingroup Modules
+* Implementation of a node for object repesentation
+*/
+class PartSet_ObjectNode : public PartSet_TreeNode
+{
+public:
+  PartSet_ObjectNode(const ObjectPtr& theObj, ModuleBase_ITreeNode* theParent = 0)
+    : PartSet_TreeNode(theParent), myObject(theObj) {}
+
+  static std::string typeId()
+  {
+    static std::string myType = "Object";
+    return myType;
+  }
+
+  virtual std::string type() const { return typeId(); }
+
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const;
+
+  /// Returns properties flag of the item
+  virtual Qt::ItemFlags flags(int theColumn) const;
+
+  /// Returns object referenced by the node (can be null)
+  virtual ObjectPtr object() const { return myObject; }
+
+  /// Sets an object to the node
+  /// theObj a new object
+  void setObject(ObjectPtr theObj) { myObject = theObj; }
+
+  virtual VisibilityState visibilityState() const;
+
+  /// Updates sub-nodes of the node
+  virtual void update();
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects);
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup);
+
+protected:
+  ObjectPtr myObject;
+};
+
+/**
+* \ingroup Modules
+* Implementation of aFolder node in data tree
+*/
+class PartSet_FolderNode : public PartSet_TreeNode
+{
+public:
+  enum FolderType {
+    ParametersFolder,
+    ConstructionFolder,
+    PartsFolder,
+    ResultsFolder,
+    FieldsFolder,
+    GroupsFolder
+  };
+
+  PartSet_FolderNode(ModuleBase_ITreeNode* theParent, FolderType theType);
+
+  static std::string typeId()
+  {
+    static std::string myType = "Folder";
+    return myType;
+  }
+
+  virtual std::string type() const { return typeId(); }
+
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const;
+
+  /// Returns properties flag of the item
+  virtual Qt::ItemFlags flags(int theColumn) const;
+
+  /// Updates sub-nodes of the node
+  virtual void update();
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects);
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup);
+
+  QString name() const;
+
+  /// Returns a node which belongs to the given document and contains objects of the given group
+  /// \param theDoc a document
+  /// \param theGroup a name of objects group
+  /// \return a parent node if it is found
+  virtual ModuleBase_ITreeNode* findParent(const DocumentPtr& theDoc, QString theGroup)
+  {
+    if ((theDoc == document()) && (theGroup.toStdString() == groupName()))
+      return this;
+    return 0;
+  }
+
+private:
+  std::string groupName() const;
+
+  ModuleBase_ITreeNode* createNode(const ObjectPtr& theObj);
+
+  FolderType myType;
+};
+
+/////////////////////////////////////////////////////////////////////
+/**
+* \ingroup Modules
+* A base class for root folders
+*/
+class PartSet_FeatureFolderNode : public PartSet_TreeNode
+{
+public:
+  PartSet_FeatureFolderNode(ModuleBase_ITreeNode* theParent = 0) : PartSet_TreeNode(theParent) {}
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects);
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup);
+
+  /// Returns a node which belongs to the given document and contains objects of the given group
+  /// \param theDoc a document
+  /// \param theGroup a name of objects group
+  /// \return a parent node if it is found
+  virtual ModuleBase_ITreeNode* findParent(const DocumentPtr& theDoc, QString theGroup);
+
+protected:
+  virtual ModuleBase_ITreeNode* createNode(const ObjectPtr& theObj) = 0;
+
+  virtual int numberOfFolders() const { return 0; }
+};
+
+
+/////////////////////////////////////////////////////////////////////
+/**
+* \ingroup Modules
+* Implementation of Root node in data tree
+*/
+class PartSet_RootNode : public PartSet_FeatureFolderNode
 {
 public:
   PartSet_RootNode();
 
+  static std::string typeId()
+  {
+    static std::string myType = "PartSetRoot";
+    return myType;
+  }
+
+  virtual std::string type() const { return typeId(); }
+
+  /// Updates sub-nodes of the node
+  virtual void update();
+
+  virtual ModuleBase_IWorkshop* workshop() const { return myWorkshop; }
+
+  /// Returns document object of the sub-tree.
+  virtual DocumentPtr document() const;
+
+  void setWorkshop(ModuleBase_IWorkshop* theWork) { myWorkshop = theWork; }
+
+protected:
+  virtual ModuleBase_ITreeNode* createNode(const ObjectPtr& theObj);
+
+  virtual int numberOfFolders() const { return 3; }
+
+private:
+  PartSet_FolderNode* myParamsFolder;
+  PartSet_FolderNode* myConstrFolder;
+  PartSet_FolderNode* myPartsFolder;
+
+  ModuleBase_IWorkshop* myWorkshop;
+};
+
+/////////////////////////////////////////////////////////////////////
+/**
+* \ingroup Modules
+* Implementation of Root node of a Part document in data tree
+*/
+class PartSet_PartRootNode : public PartSet_FeatureFolderNode
+{
+public:
+  PartSet_PartRootNode(const ObjectPtr& theObj, ModuleBase_ITreeNode* theParent);
+
+  static std::string typeId()
+  {
+    static std::string myType = "PartRoot";
+    return myType;
+  }
+
+  virtual std::string type() const { return typeId(); }
+
+  /// Returns object referenced by the node (can be null)
+  virtual ObjectPtr object() const { return myObject; }
+
+  /// Returns document object of the sub-tree.
+  virtual DocumentPtr document() const;
+
+  /// Updates sub-nodes of the node
+  virtual void update();
+
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const;
+
+  /// Returns properties flag of the item
+  virtual Qt::ItemFlags flags(int theColumn) const;
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects);
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup);
+
+protected:
+  virtual ModuleBase_ITreeNode* createNode(const ObjectPtr& theObj);
+
+  virtual int numberOfFolders() const;
+
+  virtual void deleteChildren();
+
+private:
+  PartSet_FolderNode* myParamsFolder;
+  PartSet_FolderNode* myConstrFolder;
+  PartSet_FolderNode* myResultsFolder;
+  PartSet_FolderNode* myFieldsFolder;
+  PartSet_FolderNode* myGroupsFolder;
+
+  ObjectPtr myObject;
 };
 
+/////////////////////////////////////////////////////////////////////
+/**
+* \ingroup Modules
+* Implementation of a folder which corresponds to ModelAPI_Folder object
+*/
+class PartSet_ObjectFolderNode : public PartSet_ObjectNode
+{
+public:
+  PartSet_ObjectFolderNode(const ObjectPtr& theObj, ModuleBase_ITreeNode* theParent)
+    : PartSet_ObjectNode(theObj, theParent) {}
+
+  static std::string typeId()
+  {
+    static std::string myType = "ObjectFolder";
+    return myType;
+  }
+
+  virtual std::string type() const { return typeId(); }
+
+  /// Updates sub-nodes of the node
+  virtual void update();
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects);
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup);
+
+private:
+  FeaturePtr getFeature(const std::string& theId) const;
+
+  void getFirstAndLastIndex(int& theFirst, int& theLast) const;
+};
+
+
+/////////////////////////////////////////////////////////////////////
+/**
+* \ingroup Modules
+* Implementation of a node for compsolid representation
+*/
+//class PartSet_CompsolidNode : public PartSet_ObjectNode
+//{
+//public:
+//  PartSet_CompsolidNode(const ObjectPtr& theObj, ModuleBase_ITreeNode* theParent);
+//
+//  static std::string typeId()
+//  {
+//    static std::string myType = "CompSolid";
+//    return myType;
+//  }
+//
+//  virtual std::string type() const { return typeId(); }
+//
+//  /// Updates sub-nodes of the node
+//  virtual void update();
+//
+//  /// Process creation of objects.
+//  /// \param theObjects a list of created objects
+//  /// \return a list of nodes which corresponds to the created objects
+//  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects);
+//
+//  /// Process deletion of objects.
+//  /// \param theDoc a document where objects were deleted
+//  /// \param theGroup a name of group where objects were deleted
+//  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup);
+//
+//};
 
-#endif
\ No newline at end of file
+#endif
index 49f89d9c033ac2a308aade1b1a558a10846ac122..32fea83989156974e215e1ba842a8fc613b67ce2 100755 (executable)
@@ -44,7 +44,7 @@
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_Object.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Tools.h>
 
@@ -558,7 +558,7 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
           for(int i = 0; i < aCurSelList->size(); i++) {
             std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
             ResultPtr aCurSelContext = aCurSel->context();
-            ResultCompSolidPtr aCurSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aCurSelContext);
+            ResultBodyPtr aCurSelCompSolidPtr = ModelAPI_Tools::bodyOwner(aCurSelContext);
             std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
             if(aCurSelCompSolidPtr.get()) {
               aCurSelCompSolid = aCurSelCompSolidPtr->shape();
@@ -566,8 +566,8 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
             for(int j = 0; j < aRefSelList->size(); j++) {
               std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
               ResultPtr aRefSelContext = aRefSel->context();
-              ResultCompSolidPtr aRefSelCompSolidPtr =
-                ModelAPI_Tools::compSolidOwner(aRefSelContext);
+              ResultBodyPtr aRefSelCompSolidPtr =
+                ModelAPI_Tools::bodyOwner(aRefSelContext);
               std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
               if(aRefSelCompSolidPtr.get()) {
                 aRefSelCompSolid = aRefSelCompSolidPtr->shape();
index 921abf09a88dd17331ff83b9729f3050476881c3..e2ba9dfe41141aebb33d4bac25315eeb37ad3d89 100644 (file)
@@ -198,6 +198,17 @@ def testHaveNamingEdges(theFeature, theModel, thePartDoc) :
     assert(shape.isEdge())
     assert(name != ""), "String empty"
 
+def lowerLevelSubResults(theResult, theList):
+  """ Collects in a list all lover level sub-results (without children).
+  Auxiliary method for context correct definition.
+  """
+  nbSubs = theResult.numberOfSubs()
+  if nbSubs == 0:
+    theList.append(theResult)
+  else:
+    for sub in range(0, nbSubs):
+      lowerLevelSubResults(theResult.subResult(sub), theList)
+
 def testHaveNamingByType(theFeature, theModel, thePartDoc, theSubshapeType) :
   """ Tests if all sub-shapes of result have a unique name
   :param theFeature: feature to test.
@@ -206,22 +217,14 @@ def testHaveNamingByType(theFeature, theModel, thePartDoc, theSubshapeType) :
   if not theFeature.results():
     return
   aFirstRes = theFeature.results()[0]
-  # Get number of sub-results
-  hasSubs = True
-  nbSubs = aFirstRes.numberOfSubs()
-  if nbSubs == 0:
-    # no sub-results => treat current result as a sub
-    hasSubs = False
-    nbSubs = 1
+  aResList = []
+  lowerLevelSubResults(aFirstRes, aResList)
 
   selectionList = []
   shapesList = [] # to append only unique shapes (not isSame)
-  for sub in range(0, nbSubs):
+  for aR in aResList:
     # Get feature result/sub-result
-    if hasSubs:
-      aResult = aFirstRes.subResult(sub).resultSubShapePair()[0]
-    else:
-      aResult = aFirstRes.resultSubShapePair()[0]
+    aResult = aR.resultSubShapePair()[0]
     # Get result/sub-result shape
     shape = aResult.shape()
     # Create shape explorer with desired shape type
index 8f30aa70d255071eba9bcd450e63cf7cc9886df0..8e976d02b9dd8d370fc3f515ddd47be4e2c30900 100644 (file)
@@ -163,14 +163,15 @@ void SketchSolver_Manager::processEvent(
   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
     std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleteMsg =
       std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
-    const std::set<std::string>& aFeatureGroups = aDeleteMsg->groups();
+    const std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>& aFeatureGroups =
+      aDeleteMsg->groups();
 
     // Find SketchPlugin_Sketch::ID() in groups.
     // The constraint groups should be updated when an object removed from Sketch
-    std::set<std::string>::const_iterator aFGrIter;
+    std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>::const_iterator aFGrIter;
     for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++)
-      if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0 ||
-          aFGrIter->compare(ModelAPI_Feature::group()) == 0)
+      if (aFGrIter->second == ModelAPI_ResultConstruction::group() ||
+        aFGrIter->second == ModelAPI_Feature::group())
         break;
 
     if (aFGrIter != aFeatureGroups.end()) {
index 051402c908ebb3bff6077ce63741c944129af17c..5cfb093044560a612438d04079886a28c6f99257 100644 (file)
 //
 
 #include "XGUI_DataModel.h"
-#include "XGUI_Workshop.h"
 #include "XGUI_ObjectsBrowser.h"
-#include "XGUI_Displayer.h"
 
 #include <ModuleBase_IconFactory.h>
+#include <ModuleBase_ITreeNode.h>
 
 #include <ModelAPI_Session.h>
-#include <ModelAPI_Events.h>
-#include <ModelAPI_ResultParameter.h>
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_ResultPart.h>
-#include <ModelAPI_Feature.h>
-#include <ModelAPI_CompositeFeature.h>
-#include <ModelAPI_ResultCompSolid.h>
-#include <ModelAPI_ResultField.h>
-#include <ModelAPI_Tools.h>
-#include <ModelAPI_Folder.h>
-#include <ModelAPI_AttributeReference.h>
 
 #include <Config_FeatureMessage.h>
-#include <Config_DataModelReader.h>
 
 #include <Events_Loop.h>
 
-#include <QIcon>
-#include <QBrush>
-
-#define ACTIVE_COLOR QColor(Qt::black)
-//#define ACTIVE_COLOR QColor(0,72,140)
-//#define PASSIVE_COLOR Qt::black
-
-/// Returns ResultPart object if the given object is a Part feature
-/// Otherwise returns NULL
-
-#define SELECTABLE_COLOR QColor(110, 110, 110)
-#define DISABLED_COLOR QColor(200, 200, 200)
-
-
-ResultPartPtr getPartResult(ModelAPI_Object* theObj)
-{
-  ModelAPI_Feature* aFeature = dynamic_cast<ModelAPI_Feature*>(theObj);
-  if (aFeature) {
-    ResultPtr aRes = aFeature->firstResult();
-    if (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group())) {
-      ResultPartPtr aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aRes);
-      // Use only original parts, not a placement results
-      if (aPartRes == aPartRes->original())
-      return aPartRes;
-    }
-  }
-  return ResultPartPtr();
-}
-
-/// Returns pointer on document if the given object is document object
-ModelAPI_Document* getSubDocument(void* theObj)
-{
-  ModelAPI_Document* aDoc = 0;
-  try {
-    aDoc = dynamic_cast<ModelAPI_Document*>((ModelAPI_Entity*)theObj);
-  } catch(...) {}
-  return aDoc;
-}
-
+#include <cassert>
 
 
 
@@ -108,256 +57,92 @@ XGUI_DataModel::~XGUI_DataModel()
 //******************************************************
 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
 {
-  //if (myIsEventsProcessingBlocked)
-  //  return;
-  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-  std::string aRootType = myXMLReader->rootType();
-  std::string aSubType = myXMLReader->subType();
-  int aNbFolders = foldersCount();
-
-  // Created object event *******************
   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
-
+    QObjectPtrList aCreated;
     std::set<ObjectPtr>::const_iterator aIt;
-    std::string aObjType;
-    for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
-      ObjectPtr aObject = (*aIt);
-      // We do not show objects which does not need to be shown in object browser
-      if (!aObject->isInHistory())
-        continue;
-
-      aObjType = aObject->groupName();
-      DocumentPtr aDoc = aObject->document();
-      if (aDoc == aRootDoc) {
-        // Check that new folders could appear
-        QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
-        foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-          if ((aNotEmptyFolder.toStdString() == aObjType) && (aRootDoc->size(aObjType) > 0)) {
-            // Appears first object in folder which can not be shown empty
-            if (!hasShownFolder(aRootDoc, aNotEmptyFolder)) {
-              insertRow(myXMLReader->rootFolderId(aObjType));
-              addShownFolder(aRootDoc, aNotEmptyFolder);
-            }
-          }
-        }
-        // Insert new object
-        int aRow = aRootDoc->size(aObjType) - 1;
-        if (aRow != -1) {
-          if ((aObjType == aRootType) || (aObjType == ModelAPI_Folder::group())) {
-            insertRow(aRow + aNbFolders + 1);
-          } else {
-            int aFolderId = myXMLReader->rootFolderId(aObjType);
-            if (aFolderId != -1) {
-              insertRow(aRow, createIndex(aFolderId, 0, (void*)Q_NULLPTR));
-            }
-          }
-        }
-      } else {
-        // Object created in sub-document
-        QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
-        if (aDocRoot.isValid()) {
-          // Check that new folders could appear
-          QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
-          foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-            if ((aNotEmptyFolder.toStdString() == aObjType) && (aDoc->size(aObjType) > 0)) {
-              // Appears first object in folder which can not be shown empty
-              if (!hasShownFolder(aDoc, aNotEmptyFolder)) {
-                insertRow(myXMLReader->subFolderId(aObjType), aDocRoot);
-                addShownFolder(aDoc, aNotEmptyFolder);
-              }
-            }
-         }
-          int aRow = aDoc->index(aObject, true);
-          if (aRow != -1) {
-            int aNbSubFolders = foldersCount(aDoc.get());
-            if ((aObjType == aSubType) || (aObjType == ModelAPI_Folder::group())) {
-              // List of objects under document root
-              insertRow(aRow + aNbSubFolders, aDocRoot);
-            } else {
-              // List of objects under a folder
-              if (aRow != -1) {
-                int aFolderId = folderId(aObjType, aDoc.get());
-                if (aFolderId != -1) {
-                  QModelIndex aParentFolder = createIndex(aFolderId, 0, aDoc.get());
-                  insertRow(aRow, aParentFolder);
-                  emit dataChanged(aParentFolder, aParentFolder);
-                }
-              }
-            }
-          } else {
-            rebuildDataTree();
-            break;
-          }
-        } else {
-          rebuildDataTree();
-          break;
-        }
-      }
+    for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
+      if ((*aIt)->isInHistory())
+        aCreated.append(*aIt);
+    }
+    QTreeNodesList aNodes = myRoot->objectCreated(aCreated);
+    ModuleBase_ITreeNode* aParent;
+    int aRow = 0;
+    QModelIndex aParentIndex1, aParentIndex2;
+    foreach(ModuleBase_ITreeNode* aNode, aNodes) {
+      aParent = aNode->parent();
+      aRow = aParent->nodeRow(aNode);
+      aParentIndex1 = getParentIndex(aNode, 0);
+      aParentIndex2 = getParentIndex(aNode, 2);
+      insertRows(aRow, 1, aParentIndex1);
+      dataChanged(aParentIndex1, aParentIndex2);
     }
-    // Deleted object event ***********************
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
-    std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
-    DocumentPtr aDoc = aUpdMsg->document();
-    std::set<std::string> aMsgGroups = aUpdMsg->groups();
+  }
+  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
+      std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
+          std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
+      const std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>& aMsgGroups =
+        aUpdMsg->groups();
+      std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>::const_iterator aIt;
+      for (aIt = aMsgGroups.cbegin(); aIt != aMsgGroups.cend(); aIt++)
+        QTreeNodesList aList = myRoot->objectsDeleted(aIt->first, aIt->second.c_str());
+      rebuildDataTree();
+  }
+  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
+    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
+      std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+    std::set<ObjectPtr> aObjects = aUpdMsg->objects();
 
-    /// Sort groups because RootType deletion has to be done after others
-    std::string aType = (aDoc == aRootDoc)? aRootType : aSubType;
-    std::list<std::string> aGroups;
-    std::set<std::string>::const_iterator aSetIt;
-    for (aSetIt = aMsgGroups.begin(); aSetIt != aMsgGroups.end(); ++aSetIt) {
-      std::string aGroup = (*aSetIt);
-      if (aGroup == aType)
-        aGroups.push_back(aGroup);
-      else
-        aGroups.push_front(aGroup);
-    }
+    QObjectPtrList aCreated;
+    std::set<ObjectPtr>::const_iterator aIt;
+    bool aRebuildAll = false;
+    for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
+      ObjectPtr aObj = (*aIt);
+      if (!aObj->isInHistory())
+        continue;
 
-    std::list<std::string>::const_iterator aIt;
-    for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
-      std::string aGroup = (*aIt);
-      if (aDoc == aRootDoc) {  // If root objects
-        int aRow = aRootDoc->size(aGroup, true);
-        if (aGroup == aRootType) {
-          // Process root folder
-          // remove optimization due to the issue #2456
-          //removeRow(aRow + aNbFolders);
-          //rebuildBranch(aNbFolders, aRow);
-          rebuildDataTree();
-        } else if (aGroup == ModelAPI_Folder::group()) {
-          rebuildDataTree();
-        } else {
-          // Process root sub-folder
-          int aFolderId = myXMLReader->rootFolderId(aGroup);
-          if (aFolderId != -1) {
-            QModelIndex aFolderIndex = createIndex(aFolderId, 0, (void*)Q_NULLPTR);
-            removeRow(aRow, aFolderIndex);
-            //rebuildBranch(0, aRow);
-          }
-        }
-        // Check that some folders could erased
-        QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
-        foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-          if ((aNotEmptyFolder.toStdString() == aGroup) && (aRootDoc->size(aGroup, true) == 0)) {
-            // Appears first object in folder which can not be shown empty
-            removeRow(myXMLReader->rootFolderId(aGroup));
-            removeShownFolder(aRootDoc, aNotEmptyFolder);
-            //rebuildBranch(0, aNbFolders + aDoc->size(myXMLReader->rootType()));
-            break;
-          }
-        }
-      } else {
-        // Remove row for sub-document
-        QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
-        if (aDocRoot.isValid()) {
-          int aRow = aDoc->size(aGroup, true);
-          int aNbSubFolders = foldersCount(aDoc.get());
-          if (aGroup == aSubType) {
-            // List of objects under document root
-            removeRow(aRow + aNbSubFolders, aDocRoot);
-            rebuildBranch(aNbSubFolders, aRow, aDocRoot);
-          } if (aGroup == ModelAPI_Folder::group()) {
-            rebuildDataTree();
-          } else {
-            // List of objects under a folder
-            int aFolderId = folderId(aGroup, aDoc.get());
-            if (aFolderId != -1) {
-              QModelIndex aFolderRoot = createIndex(aFolderId, 0, aDoc.get());
-              removeRow(aRow, aFolderRoot);
-              //rebuildBranch(0, aRow, aFolderRoot);
-            }
-          }
-          // Check that some folders could disappear
-          QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
-          int aSize = aDoc->size(aGroup, true);
-          foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-            if ((aNotEmptyFolder.toStdString() == aGroup) && (aSize == 0)) {
-              // Appears first object in folder which can not be shown empty
-              removeRow(myXMLReader->subFolderId(aGroup), aDocRoot);
-              removeShownFolder(aDoc, aNotEmptyFolder);
-              //rebuildBranch(0, aNbSubFolders + aDoc->size(myXMLReader->subType()), aDocRoot);
-              break;
-            }
-          }
-        } else {
-          rebuildDataTree();
+      if (aObj->data()->isValid()) {
+        if (aObj->groupName() == ModelAPI_Folder::group()) {
+          aRebuildAll = true;
           break;
         }
+        aCreated.append(*aIt);
       }
     }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    std::set<ObjectPtr> aObjects = aUpdMsg->objects();
-
-    std::set<ObjectPtr>::const_iterator aIt;
-    for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
-      ObjectPtr aObject = (*aIt);
-      if (aObject->data()->isValid()) {
-        FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
-        if (aFeature.get() && aFeature->firstResult().get()
-          && (aFeature->firstResult()->groupName() == ModelAPI_ResultField::group())) {
-            ResultFieldPtr aResult =
-              std::dynamic_pointer_cast<ModelAPI_ResultField>(aFeature->firstResult());
-            QModelIndex aIndex = objectIndex(aResult, 0);
-            removeRows(0, aResult->stepsSize(), aIndex);
-        } else {
-          if (aObject->groupName() == ModelAPI_Folder::group()) {
-            rebuildDataTree();
-          } else {
-            QModelIndex aIndex = objectIndex(aObject, 0);
-            if (aIndex.isValid()) {
-              emit dataChanged(aIndex, aIndex);
-            }
-          }
+    if (aRebuildAll) {
+      myRoot->update();
+      rebuildDataTree();
+    } else {
+      foreach(ObjectPtr aObj, aCreated) {
+        ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
+        if (aNode) {
+          QModelIndex aFirstIdx = getIndex(aNode, 0);
+          QModelIndex aLastIdx = getIndex(aNode, 2);
+          dataChanged(aFirstIdx, aLastIdx);
         }
-      } else {
-        rebuildDataTree();
-        break;
       }
     }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) {
+  }
+  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) {
     std::shared_ptr<ModelAPI_OrderUpdatedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_OrderUpdatedMessage>(theMessage);
+      std::dynamic_pointer_cast<ModelAPI_OrderUpdatedMessage>(theMessage);
     if (aUpdMsg->reordered().get()) {
       DocumentPtr aDoc = aUpdMsg->reordered()->document();
       std::string aGroup = aUpdMsg->reordered()->group();
-
-      QModelIndex aParent;
-      int aStartId = 0;
-      if (aDoc == aRootDoc) {
-        // Update a group under root
-        if (aGroup == myXMLReader->rootType()) // Update objects under root
-          aStartId = foldersCount();
-        else // Update objects in folder under root
-          aParent = createIndex(folderId(aGroup), 0, (void*)Q_NULLPTR);
-      } else {
-        // Update a sub-document
-        if (aGroup == myXMLReader->subType()) {
-          // Update sub-document root
-          aParent = findDocumentRootIndex(aDoc.get(), 0);
-          aStartId = foldersCount(aDoc.get());
-        } else
-          // update folder in sub-document
-          aParent = createIndex(folderId(aGroup, aDoc.get()), 0, aDoc.get());
+      ModuleBase_ITreeNode* aNode = myRoot->findParent(aDoc, aGroup.c_str());
+      if (aNode) {
+        aNode->update();
+        updateSubTree(aNode);
       }
-      int aChildNb = rowCount(aParent);
-      rebuildBranch(aStartId, aChildNb - aStartId, aParent);
-    } else {
-      rebuildDataTree();
     }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
+  }
+  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
     DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument();
-    if (aDoc != aRootDoc) {
-      QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
-      if (aDocRoot.isValid())
-        emit dataChanged(aDocRoot, aDocRoot);
-      else
-        // We have got a new document
-        rebuildDataTree();
+    ModuleBase_ITreeNode* aRoot = myRoot->findRoot(aDoc);
+    if (aRoot) {
+      updateSubTree(aRoot);
     }
   }
 }
@@ -380,192 +165,29 @@ void XGUI_DataModel::rebuildDataTree()
 //******************************************************
 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
 {
-  if (theIndex.internalId() == 0) // this is a folder
-    return ObjectPtr();
-  ModelAPI_Object* aObj = 0;
-  try {
-    aObj = dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theIndex.internalPointer());
-  } catch(...) {}
-
-  if (!aObj)
-    return ObjectPtr();
-  if (getSubDocument(aObj)) // the selected index is a folder of sub-document
-    return ObjectPtr();
-
-  return aObj->data()->owner();
+  if (theIndex.isValid()) {
+    ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+    return aNode->object();
+  }
+  return ObjectPtr();
 }
 
 //******************************************************
 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const
 {
-  std::string aType = theObject->groupName();
-  DocumentPtr aDoc = theObject->document();
-  int aRow = aDoc->index(theObject, true);
-  if (aRow == -1) {
-    // it could be a part of complex object
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
-    if (aFeature.get()) {
-      CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
-      if (aCompFea.get()) {
-        for (int i = 0; i < aCompFea->numberOfSubs(true); i++) {
-          if (aCompFea->subFeature(i, true) == theObject) {
-            aRow = i;
-            break;
-          }
-        }
-      }
-      int aFRow = -1;
-      FolderPtr aFolder = aDoc->findContainingFolder(aFeature, aFRow);
-      if (aFolder.get())
-        aRow = aFRow;
-    } else {
-      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
-      if (aResult.get()) {
-        ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
-        if (aCompRes.get()) {
-          aRow = ModelAPI_Tools::compSolidIndex(aResult);
-        }
-      }
-    }
-    if (aRow == -1)
-      return QModelIndex();
-    else
-      return createIndex(aRow, theColumn, theObject.get());
+  ModuleBase_ITreeNode* aNode = myRoot->subNode(theObject);
+  if (aNode) {
+    return getIndex(aNode, theColumn);
   }
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  if (aDoc == aRootDoc &&
-    ((myXMLReader->rootType() == aType) || (aType == ModelAPI_Folder::group()))) {
-    // The object from root document
-    aRow += foldersCount();
-  } else if ((myXMLReader->subType() == aType) || (aType == ModelAPI_Folder::group())) {
-    // The object from sub document
-    aRow += foldersCount(aDoc.get());
-  }
-  return createIndex(aRow, theColumn, theObject.get());
+  return QModelIndex();
 }
 
 //******************************************************
 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
 {
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  int aNbFolders = foldersCount();
-  int theIndexRow = theIndex.row();
-
-  if (theRole == Qt::DecorationRole) {
-    if (theIndex == lastHistoryIndex())
-      return QIcon(":pictures/arrow.png");
-    else if (theIndex.column() == 0) {
-      VisibilityState aState = getVisibilityState(theIndex);
-      switch (aState) {
-      case NoneState:
-        return QIcon();
-      case Visible:
-        return QIcon(":pictures/eyeopen.png");
-      case SemiVisible:
-        return QIcon(":pictures/eyemiclosed.png");
-      case Hidden:
-        return QIcon(":pictures/eyeclosed.png");
-      }
-    }
-  }
-
-  //if (theIndex.column() == 1)
-  if (theIndex.column() != 1)
-    return QVariant();
-
-  quintptr aParentId = theIndex.internalId();
-  if (aParentId == 0) { // root folders
-    switch (theRole) {
-      case Qt::DisplayRole:
-        return QString(myXMLReader->rootFolderName(theIndexRow).c_str()) +
-          QString(" (%1)").arg(rowCount(theIndex));
-      case Qt::DecorationRole:
-        return QIcon(myXMLReader->rootFolderIcon(theIndexRow).c_str());
-      case Qt::ForegroundRole:
-        {
-          Qt::ItemFlags aFlags = theIndex.flags();
-          if (aFlags == Qt::ItemFlags())
-            return QBrush(DISABLED_COLOR);
-          if (!aFlags.testFlag(Qt::ItemIsEditable))
-            return QBrush(SELECTABLE_COLOR);
-        }
-        return ACTIVE_COLOR;
-    }
-  } else { // an object or sub-document
-    if (theRole == Qt::ForegroundRole) {
-      Qt::ItemFlags aFlags = theIndex.flags();
-      if (aFlags == Qt::ItemFlags())
-        return QBrush(DISABLED_COLOR);
-      if (!aFlags.testFlag(Qt::ItemIsEditable))
-        return QBrush(SELECTABLE_COLOR);
-      return ACTIVE_COLOR;
-    }
-
-    ModelAPI_Document* aSubDoc = getSubDocument(theIndex.internalPointer());
-    if (aSubDoc) { // this is a folder of sub document
-      QIntList aMissedIdx = missedFolderIndexes(aSubDoc);
-      int aRow = theIndexRow;
-      while (aMissedIdx.contains(aRow))
-        aRow++;
-      if (aRow < myXMLReader->subFoldersNumber()) {
-        switch (theRole) {
-          case Qt::DisplayRole:
-            return QString(myXMLReader->subFolderName(aRow).c_str()) +
-              QString(" (%1)").arg(rowCount(theIndex));
-          case Qt::DecorationRole:
-            return QIcon(myXMLReader->subFolderIcon(aRow).c_str());
-        }
-      }
-    } else {
-      ObjectPtr aObj = object(theIndex);
-      if (aObj) {
-        switch (theRole) {
-        case Qt::DisplayRole:
-          {
-            if (aObj->groupName() == ModelAPI_ResultParameter::group()) {
-              ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObj);
-              AttributeDoublePtr aValueAttribute =
-                aParam->data()->real(ModelAPI_ResultParameter::VALUE());
-              QString aVal = QString::number(aValueAttribute->value());
-              QString aTitle = QString(aObj->data()->name().c_str());
-              return aTitle + " = " + aVal;
-            }
-            QString aSuffix;
-            if (aObj->groupName() == myXMLReader->subType()) {
-              ResultPartPtr aPartRes = getPartResult(aObj.get());
-              if (aPartRes.get()) {
-                if (aPartRes->partDoc().get() == NULL)
-                  aSuffix = " (Not loaded)";
-              }
-            }
-            return aObj->data()->name().c_str() + aSuffix;
-          }
-        case Qt::DecorationRole:
-          {
-            if (aObj->groupName() == ModelAPI_Folder::group())
-              return QIcon(":pictures/features_folder.png");
-            else
-              return ModuleBase_IconFactory::get()->getIcon(aObj);
-          }
-        }
-      } else {
-        switch (theRole) {
-        case Qt::DisplayRole:
-          {
-            ModelAPI_ResultField::ModelAPI_FieldStep* aStep =
-              dynamic_cast<ModelAPI_ResultField::ModelAPI_FieldStep*>
-              ((ModelAPI_Entity*)theIndex.internalPointer());
-            if (aStep) {
-              return "Step " + QString::number(aStep->id() + 1) + " " +
-                aStep->field()->textLine(aStep->id()).c_str();
-            }
-          }
-          break;
-        }
-      }
-    }
+  if (theIndex.isValid()) {
+    ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+    return aNode->data(theIndex.column(), theRole);
   }
   return QVariant();
 }
@@ -579,74 +201,9 @@ QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, i
 //******************************************************
 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
 {
-  SessionPtr aSession = ModelAPI_Session::get();
-  if (!aSession->hasModuleDocument())
-    return 0;
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-
-  if (!theParent.isValid()) {
-    // Return number of items in root
-    int aNbFolders = foldersCount();
-    int aNbItems = 0;
-    std::string aType = myXMLReader->rootType();
-    if (!aType.empty())
-      aNbItems = aRootDoc->size(aType, true);
-    return aNbFolders + aNbItems;
-  }
-
-  quintptr aId = theParent.internalId();
-  if (aId == 0) {
-    // this is a folder under root
-    int aParentPos = theParent.row();
-    std::string aType = myXMLReader->rootFolderType(aParentPos);
-    return aRootDoc->size(aType);
-  } else {
-    // It is an object which could have children
-    ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
-    if (aDoc) {
-      // a folder of sub-document
-      QIntList aMissedIdx = missedFolderIndexes(aDoc);
-      int aRow = theParent.row();
-      while (aMissedIdx.contains(aRow))
-        aRow++;
-      if (aRow < myXMLReader->subFoldersNumber()) {
-        std::string aType = myXMLReader->subFolderType(aRow);
-        return aDoc->size(aType);
-      }
-    } else {
-      ModelAPI_Object* aObj =
-        dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theParent.internalPointer());
-      // Check for Part feature
-      ResultPartPtr aPartRes = getPartResult(aObj);
-      if (aPartRes.get()) {
-        DocumentPtr aSubDoc = aPartRes->partDoc();
-        if (!aSubDoc.get())
-          return 0;
-
-        int aNbSubFolders = foldersCount(aSubDoc.get());
-        int aNbSubItems = 0;
-        std::string aSubType = myXMLReader->subType();
-        if (!aSubType.empty())
-          aNbSubItems = aSubDoc->size(aSubType, true);
-        return aNbSubItems + aNbSubFolders;
-      } else {
-        // Check for composite object
-        ModelAPI_CompositeFeature* aCompFeature = dynamic_cast<ModelAPI_CompositeFeature*>(aObj);
-        if (aCompFeature)
-          return aCompFeature->numberOfSubs(true);
-        ModelAPI_ResultCompSolid* aCompRes = dynamic_cast<ModelAPI_ResultCompSolid*>(aObj);
-        if (aCompRes)
-          return aCompRes->numberOfSubs(true);
-        ModelAPI_ResultField* aFieldRes = dynamic_cast<ModelAPI_ResultField*>(aObj);
-        if (aFieldRes)
-          return aFieldRes->stepsSize();
-        ModelAPI_Folder* aFolder = dynamic_cast<ModelAPI_Folder*>(aObj);
-        if (aFolder)
-          return getNumberOfFolderItems(aFolder);
-      }
-    }
-  }
-  return 0;
+  ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
+    (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
+  return aParentNode->childrenCount();
 }
 
 //******************************************************
@@ -658,181 +215,20 @@ int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
 //******************************************************
 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
 {
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  int aNbFolders = foldersCount();
-
-  QModelIndex aIndex;
-
-  if (!theParent.isValid()) {
-    if (theRow < aNbFolders) // Return first level folder index
-      return createIndex(theRow, theColumn, (void*)Q_NULLPTR);
-    else { // return object under root index
-      std::string aType = myXMLReader->rootType();
-      int aObjId = theRow - aNbFolders;
-      if (aObjId < aRootDoc->size(aType, true)) {
-        ObjectPtr aObj = aRootDoc->object(aType, aObjId, true);
-        aIndex = objectIndex(aObj, theColumn);
-      }
-    }
-  } else {
-    quintptr aId = theParent.internalId();
-    int aParentPos = theParent.row();
-    if (aId == 0) { // return object index inside of first level of folders
-      std::string aType = myXMLReader->rootFolderType(aParentPos);
-      if (theRow < aRootDoc->size(aType)) {
-        ObjectPtr aObj = aRootDoc->object(aType, theRow, true);
-        aIndex = objectIndex(aObj, theColumn);
-      }
-    } else {
-      // It is an object which could have children
-      ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
-      if (aDoc) {
-        // It is a folder of sub-document
-        int aParentRow = aParentPos;
-        QIntList aMissedIdx = missedFolderIndexes(aDoc);
-        while (aMissedIdx.contains(aParentRow))
-          aParentRow++;
-        if (aParentRow < myXMLReader->subFoldersNumber()) {
-          std::string aType = myXMLReader->subFolderType(aParentRow);
-          if (theRow < aDoc->size(aType)) {
-            ObjectPtr aObj = aDoc->object(aType, theRow);
-            aIndex = objectIndex(aObj, theColumn);
-          }
-        }
-      } else {
-        ModelAPI_Object* aParentObj =
-          dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theParent.internalPointer());
-
-        // Check for Part feature
-        ResultPartPtr aPartRes = getPartResult(aParentObj);
-        if (aPartRes.get()) {
-          DocumentPtr aSubDoc = aPartRes->partDoc();
-          int aNbSubFolders = foldersCount(aSubDoc.get());
-          if (theRow < aNbSubFolders) { // Create a Folder of sub-document
-            aIndex = createIndex(theRow, theColumn, aSubDoc.get());
-          } else {
-            // this is an object under sub document root
-            std::string aType = myXMLReader->subType();
-            ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders, true);
-            aIndex = objectIndex(aObj, theColumn);
-          }
-        } else {
-          // Check for composite object
-          ModelAPI_CompositeFeature* aCompFeature =
-            dynamic_cast<ModelAPI_CompositeFeature*>(aParentObj);
-          if (aCompFeature) {
-            aIndex = objectIndex(aCompFeature->subFeature(theRow), theColumn);
-          } else {
-            ModelAPI_ResultCompSolid* aCompRes =
-              dynamic_cast<ModelAPI_ResultCompSolid*>(aParentObj);
-            if (aCompRes)
-              aIndex = objectIndex(aCompRes->subResult(theRow), theColumn);
-            else {
-              ModelAPI_ResultField* aFieldRes =
-                dynamic_cast<ModelAPI_ResultField*>(aParentObj);
-              if (aFieldRes) {
-                aIndex = createIndex(theRow, theColumn, aFieldRes->step(theRow));
-              } else {
-                ModelAPI_Folder* aFolder = dynamic_cast<ModelAPI_Folder*>(aParentObj);
-                ObjectPtr aObj = getObjectInFolder(aFolder, theRow);
-                if (aObj.get())
-                  aIndex = objectIndex(aObj, theColumn);
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-  return aIndex;
+  int aa = theParent.row();
+  ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
+    (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
+  ModuleBase_ITreeNode* aSubNode = aParentNode->subNode(theRow);
+  assert(aSubNode);
+  return createIndex(theRow, theColumn, aSubNode);
 }
 
 //******************************************************
-static QModelIndex MYLastDeleted;
 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
 {
-  if (!theIndex.isValid())
-    return QModelIndex();
-  // To avoid additional request about index which was already deleted
-  if (theIndex == MYLastDeleted)
-    return QModelIndex();
-
-  SessionPtr aSession = ModelAPI_Session::get();
-  quintptr aId = theIndex.internalId();
-  if (aId != 0) { // The object is not a root folder
-    ModelAPI_Document* aDoc = getSubDocument(theIndex.internalPointer());
-    if (aDoc) {
-      // It is a folder of sub-document
-      return findDocumentRootIndex(aDoc);
-    }
-    ObjectPtr aObj = object(theIndex);
-    if (!aObj.get()) {
-      // It can be a step of a field
-      ModelAPI_ResultField::ModelAPI_FieldStep* aStep = 0;
-      try {
-        aStep = dynamic_cast<ModelAPI_ResultField::ModelAPI_FieldStep*>
-                ((ModelAPI_Entity*)theIndex.internalPointer());
-      } catch(...) {}
-
-      if (aStep) {
-        ModelAPI_ResultField* aField = aStep->field();
-        DocumentPtr aDoc = aSession->activeDocument();
-        ObjectPtr aFld;
-        for(int i = 0; i < aDoc->size(ModelAPI_ResultField::group()); i++) {
-          aFld = aDoc->object(ModelAPI_ResultField::group(), i);
-          if (aFld.get() == aField)
-            return objectIndex(aFld);
-        }
-      }
-      // To avoid additional request about index which was already deleted
-      // If deleted it causes a crash on delete object from Part
-      MYLastDeleted = theIndex;
-      return QModelIndex();
-    }
-    // Check is it object a sub-object of a complex object
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
-    if (aFeature.get()) {
-      CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
-      if (aCompFea.get()) {
-        return objectIndex(aCompFea);
-      }
-      DocumentPtr aDoc = aFeature->document();
-      int aRow;
-      FolderPtr aFolder = aDoc->findContainingFolder(aFeature, aRow);
-      if (aFolder.get())
-        return objectIndex(aFolder);
-    }
-    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
-    if (aResult.get()) {
-      ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
-      if (aCompRes.get()) {
-        return objectIndex(aCompRes);
-      }
-    }
-    // Use as ordinary object
-    std::string aType = aObj->groupName();
-    DocumentPtr aRootDoc = aSession->moduleDocument();
-    DocumentPtr aSubDoc = aObj->document();
-    if (aSubDoc == aRootDoc) {
-      if ((aType == myXMLReader->rootType()) || (aType == ModelAPI_Folder::group()))
-        return QModelIndex();
-      else {
-        // return first level of folder index
-        int aFolderId = myXMLReader->rootFolderId(aType);
-        // Items in a one row must have the same parent
-        return createIndex(aFolderId, 1, (void*)Q_NULLPTR);
-      }
-    } else {
-      if ((aType == myXMLReader->subType()) || (aType == ModelAPI_Folder::group()))
-        return findDocumentRootIndex(aSubDoc.get());
-      else {
-        // return first level of folder index
-        int aFolderId = folderId(aType, aSubDoc.get());
-        // Items in a one row must have the same parent
-        return createIndex(aFolderId, 1, aSubDoc.get());
-      }
-    }
+  if (theIndex.isValid()) {
+    ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+    return getParentIndex(aNode, 1);
   }
   return QModelIndex();
 }
@@ -840,7 +236,9 @@ QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
 //******************************************************
 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
 {
-  return rowCount(theParent) > 0;
+  ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
+    (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
+  return aParentNode->childrenCount() > 0;
 }
 
 //******************************************************
@@ -848,7 +246,6 @@ bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& the
 {
   beginInsertRows(theParent, theRow, theRow + theCount - 1);
   endInsertRows();
-
   return true;
 }
 
@@ -863,113 +260,13 @@ bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& the
 //******************************************************
 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
 {
-  quintptr aIt = theIndex.internalId();
-  ModelAPI_Object* aObj = 0;
-  ModelAPI_Document* aDoc = 0;
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aActiveDoc = aSession->activeDocument();
-
-  Qt::ItemFlags aNullFlag;
-  Qt::ItemFlags aDefaultFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
-  Qt::ItemFlags aEditingFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
-
-
-  if (aIt == 0) {
-    // Folders under root
-    DocumentPtr aRootDoc = aSession->moduleDocument();
-    if (aRootDoc != aActiveDoc)
-      return aDefaultFlag;
-  } else {
-    aDoc = getSubDocument(theIndex.internalPointer());
-    if (!aDoc)
-      aObj = dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theIndex.internalPointer());
-  }
-
-  if (aObj) {
-    // An object
-    if (aObj->isDisabled())
-      return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag;
-
-    if (aSession->moduleDocument() != aObj->document())
-      if (aActiveDoc != aObj->document())
-        return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag;
-
-    bool isCompositeSub = false;
-    // An object which is sub-object of a composite object can not be accessible in column 2
-    if (theIndex.column() == 2) {
-      ObjectPtr aObjPtr = aObj->data()->owner();
-      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObjPtr);
-      if (aFeature.get()) {
-        CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
-        if (aCompFea.get())
-          isCompositeSub = true;
-      } else {
-        ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObjPtr);
-        if (aResult.get()) {
-          ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
-          if (aCompRes.get())
-            isCompositeSub = true;
-        }
-      }
-    }
-    if (isCompositeSub)
-      return Qt::ItemIsSelectable;
-
-    if (aObj->document() != aActiveDoc) {
-      // The object could be a root of sub-tree
-      ResultPartPtr aPartRes = getPartResult(aObj);
-      if (aPartRes.get()) {
-        if (aPartRes->partDoc() == aActiveDoc)
-          return aEditingFlag;
-      }
-      return aDefaultFlag;
-    }
-  } else if (aDoc) {
-    // A folder under sub-document
-    if (aActiveDoc.get() != aDoc)
-      return aNullFlag;
+  if (theIndex.isValid()) {
+    ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+    return aNode->flags(theIndex.column());
   }
-  return aEditingFlag;
+  return Qt::ItemFlags();
 }
 
-//******************************************************
-QModelIndex
-  XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn) const
-{
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  if (myXMLReader->isAttachToResult()) { // If document is attached to result
-    int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
-    ObjectPtr aObj;
-    ResultPartPtr aPartRes;
-    for (int i = 0; i < aNb; i++) {
-      aObj = aRootDoc->object(ModelAPI_ResultPart::group(), i);
-      aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
-      if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) {
-        int aRow = i;
-        if (myXMLReader->rootType() == ModelAPI_Feature::group()) {
-          aRow += foldersCount();
-        }
-        return createIndex(aRow, aColumn, aObj.get());
-      }
-    }
-  } else { // If document is attached to feature
-    int aNb = aRootDoc->size(ModelAPI_Feature::group(), true);
-    ObjectPtr aObj;
-    ResultPartPtr aPartRes;
-    for (int i = 0; i < aNb; i++) {
-      aObj = aRootDoc->object(ModelAPI_Feature::group(), i, true);
-      aPartRes = getPartResult(aObj.get());
-      if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) {
-        int aRow = i;
-        if (myXMLReader->rootType() == ModelAPI_Feature::group())
-          aRow += foldersCount();
-        return createIndex(aRow, aColumn, aObj.get());
-      }
-    }
-  }
-  return QModelIndex();
-}
 
 //******************************************************
 QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const
@@ -978,234 +275,66 @@ QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn)
   DocumentPtr aRootDoc = aSession->moduleDocument();
   if (theDoc == aRootDoc)
     return QModelIndex();
-  else
-    return findDocumentRootIndex(theDoc.get(), theColumn);
-}
-
-//******************************************************
-int XGUI_DataModel::foldersCount(ModelAPI_Document* theDoc) const
-{
-  int aNb = 0;
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  if ((theDoc == 0) || (theDoc == aRootDoc.get())) {
-    for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) {
-      if (myXMLReader->rootShowEmpty(i))
-        aNb++;
-      else {
-        if (aRootDoc->size(myXMLReader->rootFolderType(i)) > 0)
-          aNb++;
-      }
-    }
-  } else {
-    for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) {
-      if (myXMLReader->subShowEmpty(i))
-        aNb++;
-      else {
-        if (theDoc->size(myXMLReader->subFolderType(i)) > 0)
-          aNb++;
-      }
-    }
-  }
-  return aNb;
-}
-
-
-//******************************************************
-QIntList XGUI_DataModel::missedFolderIndexes(ModelAPI_Document* theDoc) const
-{
-  QIntList aList;
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  if ((theDoc == 0) || (theDoc == aRootDoc.get())) {
-    for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) {
-      if (!myXMLReader->rootShowEmpty(i)) {
-        if (aRootDoc->size(myXMLReader->rootFolderType(i)) == 0)
-          aList.append(i);
-      }
-    }
-  } else {
-    for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) {
-      if (!myXMLReader->subShowEmpty(i)) {
-        if (theDoc->size(myXMLReader->subFolderType(i)) == 0)
-          aList.append(i);
+  else {
+    ModuleBase_ITreeNode* aDocNode = 0;
+    foreach(ModuleBase_ITreeNode* aNode, myRoot->children()) {
+      if (aNode->document() == theDoc) {
+        aDocNode = aNode;
+        break;
       }
     }
+    if (aDocNode)
+      return getIndex(aDocNode, theColumn);
   }
-  return aList;
-}
-
-
-//******************************************************
-QStringList XGUI_DataModel::listOfShowNotEmptyFolders(bool fromRoot) const
-{
-  QStringList aResult;
-  if (fromRoot) {
-    for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) {
-      if (!myXMLReader->rootShowEmpty(i))
-        aResult << myXMLReader->rootFolderType(i).c_str();
-    }
-  } else {
-    for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) {
-      if (!myXMLReader->subShowEmpty(i))
-        aResult << myXMLReader->subFolderType(i).c_str();
-    }
-  }
-  return aResult;
+  return QModelIndex();
 }
 
 //******************************************************
-QModelIndex XGUI_DataModel::lastHistoryIndex() const
+bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
 {
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aCurDoc = aSession->activeDocument();
-  FeaturePtr aFeature = aCurDoc->currentFeature(true);
-  if (aFeature.get()) {
-    QModelIndex aInd = objectIndex(aFeature);
-    return createIndex(aInd.row(), 2, aInd.internalPointer());
-  } else {
-    if (aCurDoc == aSession->moduleDocument())
-      return createIndex(foldersCount() - 1, 2, -1);
-    else
-      return createIndex(foldersCount(aCurDoc.get()) - 1, 2, aCurDoc.get());
+  if (theIndex.isValid()) {
+    ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+    return aNode->visibilityState() == ModuleBase_ITreeNode::Hidden;
   }
+  return false;
 }
 
 //******************************************************
-bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
+bool XGUI_DataModel::hasIndex(const QModelIndex& theIndex) const
 {
-  return getVisibilityState(theIndex) == Hidden;
+  ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+  return myRoot->hasSubNode(aNode);
 }
 
 //******************************************************
-int XGUI_DataModel::folderId(std::string theType, ModelAPI_Document* theDoc) const
+QModelIndex XGUI_DataModel::getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const
 {
-  SessionPtr aSession = ModelAPI_Session::get();
-  ModelAPI_Document* aDoc = theDoc;
-  if (aDoc == 0)
-    aDoc = aSession->moduleDocument().get();
-
-  bool aUseSubDoc = (aDoc != aSession->moduleDocument().get());
-
-  int aRes = -1;
-  if (aUseSubDoc) {
-    int aId = myXMLReader->subFolderId(theType);
-    aRes = aId;
-    for (int i = 0; i < aId; i++) {
-      if (!myXMLReader->subShowEmpty(i)) {
-        if (aDoc->size(myXMLReader->subFolderType(i)) == 0)
-          aRes--;
-      }
-    }
+  ModuleBase_ITreeNode* aParent = theNode->parent();
+  if (aParent == myRoot) {
+    return QModelIndex();
   } else {
-    int aId = myXMLReader->rootFolderId(theType);
-    aRes = aId;
-    for (int i = 0; i < aId; i++) {
-      if (!myXMLReader->rootShowEmpty(i)) {
-        if (aDoc->size(myXMLReader->rootFolderType(i)) == 0)
-          aRes--;
-      }
-    }
+    return getIndex(aParent, thCol);
   }
-  return aRes;
 }
 
 //******************************************************
-void XGUI_DataModel::rebuildBranch(int theRow, int theCount, const QModelIndex& theParent)
+QModelIndex XGUI_DataModel::getIndex(ModuleBase_ITreeNode* theNode, int thCol) const
 {
-  if (theCount > 0) {
-    removeRows(theRow, theCount, theParent);
-    insertRows(theRow, theCount, theParent);
-  }
+  if (theNode == myRoot)
+    return QModelIndex();
+  int aRow = theNode->parent()->nodeRow(theNode);
+  return createIndex(aRow, thCol, theNode);
 }
 
-//******************************************************
-//bool XGUI_DataModel::blockEventsProcessing(const bool theState)
-//{
-//  bool aPreviousState = myIsEventsProcessingBlocked;
-//  myIsEventsProcessingBlocked = theState;
-//  return aPreviousState;
-//}
 
 //******************************************************
-XGUI_DataModel::VisibilityState
-  XGUI_DataModel::getVisibilityState(const QModelIndex& theIndex) const
+void XGUI_DataModel::updateSubTree(ModuleBase_ITreeNode* theParent)
 {
-  Qt::ItemFlags aFlags = theIndex.flags();
-  if (aFlags == Qt::ItemFlags())
-    return NoneState;
-
-  ObjectPtr aObj = object(theIndex);
-  if (aObj.get()) {
-    if (aObj->groupName() == ModelAPI_ResultParameter::group())
-      return NoneState;
-    ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
-    if (aResObj.get()) {
-      XGUI_Displayer* aDisplayer = myWorkshop->displayer();
-      ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResObj);
-      if (aCompRes.get()) {
-        VisibilityState aState = aCompRes->numberOfSubs(true) == 0 ?
-          (aDisplayer->isVisible(aCompRes)? Visible : Hidden) : NoneState;
-        for (int i = 0; i < aCompRes->numberOfSubs(true); i++) {
-          ResultPtr aSubRes = aCompRes->subResult(i, true);
-          VisibilityState aS = aDisplayer->isVisible(aSubRes)? Visible : Hidden;
-          if (aState == NoneState)
-            aState = aS;
-          else if (aState != aS) {
-            aState = SemiVisible;
-            break;
-          }
-        }
-        return aState;
-      } else {
-        if (aDisplayer->isVisible(aResObj))
-          return Visible;
-        else
-          return Hidden;
-      }
-    }
+  int aRows = theParent->childrenCount();
+  if (aRows) {
+    QModelIndex aParent = getIndex(theParent, 0);
+    QModelIndex aFirstIdx = aParent.child(0, 0);
+    QModelIndex aLastIdx = aParent.child(aRows - 1, 2);
+    dataChanged(aFirstIdx, aLastIdx);
   }
-  return NoneState;
-}
-
-
-int XGUI_DataModel::getNumberOfFolderItems(const ModelAPI_Folder* theFolder) const
-{
-  DocumentPtr aDoc = theFolder->document();
-
-  FeaturePtr aFirstFeatureInFolder;
-  AttributeReferencePtr aFirstFeatAttr =
-      theFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
-  if (aFirstFeatAttr)
-    aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
-  if (!aFirstFeatureInFolder.get())
-    return 0;
-
-  FeaturePtr aLastFeatureInFolder;
-  AttributeReferencePtr aLastFeatAttr =
-      theFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID());
-  if (aLastFeatAttr)
-    aLastFeatureInFolder = ModelAPI_Feature::feature(aLastFeatAttr->value());
-  if (!aLastFeatureInFolder.get())
-    return 0;
-
-  int aFirst = aDoc->index(aFirstFeatureInFolder);
-  int aLast = aDoc->index(aLastFeatureInFolder);
-  return aLast - aFirst + 1;
-}
-
-ObjectPtr XGUI_DataModel::getObjectInFolder(const ModelAPI_Folder* theFolder, int theId) const
-{
-  DocumentPtr aDoc = theFolder->document();
-
-  FeaturePtr aFirstFeatureInFolder;
-  AttributeReferencePtr aFirstFeatAttr =
-      theFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
-  if (aFirstFeatAttr)
-    aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
-  if (!aFirstFeatureInFolder.get())
-    return ObjectPtr();
-
-  int aFirst = aDoc->index(aFirstFeatureInFolder);
-  return aDoc->object(ModelAPI_Feature::group(), aFirst + theId);
 }
index e89546161dda5a6b3a564dcc0fe37741a607a222..5e446bf0e55ae13e021dfcd83b9785e29099934f 100644 (file)
@@ -31,6 +31,7 @@
 
 class Config_DataModelReader;
 class XGUI_Workshop;
+class ModuleBase_ITreeNode;
 
 /**\class XGUI_DataModel
  * \ingroup GUI
@@ -54,6 +55,11 @@ public:
   /// Destructor
   virtual ~XGUI_DataModel();
 
+
+  void setRoot(ModuleBase_ITreeNode* theRoot) { myRoot = theRoot; }
+
+  ModuleBase_ITreeNode* root() const { return myRoot; }
+
   /// Event Listener method
   /// \param theMessage an event message
   virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
@@ -72,7 +78,6 @@ public:
   //! Rebuild data tree
   virtual void rebuildDataTree();
 
-
   /// Returns the data stored under the given role for the item referred to by the index.
   /// \param theIndex a model index
   /// \param theRole a data role (see Qt::ItemDataRole)
@@ -134,10 +139,10 @@ public:
   QModelIndex documentRootIndex(DocumentPtr theDoc, int theColumn = 1) const;
 
   /// Returns last history object index
-  virtual QModelIndex lastHistoryIndex() const;
+  //virtual QModelIndex lastHistoryIndex() const;
 
   /// Initialises XML data model reader. It must be initialised before DataModel using.
-  void setXMLReader(Config_DataModelReader* theReader) { myXMLReader = theReader; }
+  //void setXMLReader(Config_DataModelReader* theReader) { myXMLReader = theReader; }
 
   /// Do not processing anymore events of model loop
   //bool blockEventsProcessing(const bool theState);
@@ -147,6 +152,10 @@ public:
   /// \return boolean value
   bool hasHiddenState(const QModelIndex& theIndex);
 
+  /// Returns true if the given index exists in data tree
+  /// \param theIndex an index to check
+  bool hasIndex(const QModelIndex& theIndex) const;
+
 signals:
   /// Signal about tree had been rebuilt
   void treeRebuilt();
@@ -158,69 +167,78 @@ private:
     SemiVisible,
     Hidden };
 
+
+  QModelIndex getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const;
+
+  QModelIndex getIndex(ModuleBase_ITreeNode* theNode, int thCol) const;
+
+  void updateSubTree(ModuleBase_ITreeNode* theParent);
+
   /// Find a root index which contains objects of the given document
   /// \param theDoc the document object
-  QModelIndex findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn = 1) const;
+  //QModelIndex findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn = 1) const;
 
   /// Returns number of folders in document.
   /// Considered folders which has to be shown only if they are not empty.
   /// \param theDoc document which has to be checked. If 0 then Root document will be considered
-  int foldersCount(ModelAPI_Document* theDoc = 0) const;
+  //int foldersCount(ModelAPI_Document* theDoc = 0) const;
 
   /// Retrurns indexes of folders which can not be shown because they are empty
   /// \param theDoc document which has to be checked. If 0 then Root document will be considered
-  QIntList missedFolderIndexes(ModelAPI_Document* theDoc = 0) const;
+  //QIntList missedFolderIndexes(ModelAPI_Document* theDoc = 0) const;
 
   /// Returns Id (row) of a folder taking into consideration
   /// folders which can not be shown non empty
   /// \param theType Type of the folder
   /// \param theDoc a document which contains this folder
-  int folderId(std::string theType, ModelAPI_Document* theDoc = 0) const;
+  //int folderId(std::string theType, ModelAPI_Document* theDoc = 0) const;
 
   /// Removes a row from branch of tree
   /// \param theStart - start row to update indexes
   /// \param theSize - number of indexes in the folder
   /// \param theParent - index of parent folder
-  void rebuildBranch(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
+  //void rebuildBranch(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
 
   /// Returns list of folders types which can not be shown empty
   /// \param fromRoot - root document flag
-  QStringList listOfShowNotEmptyFolders(bool fromRoot = true) const;
-
-  int getNumberOfFolderItems(const ModelAPI_Folder* theFolder) const;
-  ObjectPtr getObjectInFolder(const ModelAPI_Folder* theFolder, int theId) const;
-
-  VisibilityState getVisibilityState(const QModelIndex& theIndex) const;
-
-  void addShownFolder(DocumentPtr theDoc, QString theFolder)
-  {
-    if (!myShownFolders.contains(theDoc)) {
-      myShownFolders[theDoc] = QStringList();
-    }
-    myShownFolders[theDoc].append(theFolder);
-  }
-
-  void removeShownFolder(DocumentPtr theDoc, QString theFolder)
-  {
-    if (myShownFolders.contains(theDoc)) {
-      myShownFolders[theDoc].removeAll(theFolder);
-      if (myShownFolders[theDoc].isEmpty())
-        myShownFolders.remove(theDoc);
-    }
-  }
-
-  bool hasShownFolder(DocumentPtr theDoc, QString theFolder) const
-  {
-    if (myShownFolders.contains(theDoc))
-      return myShownFolders[theDoc].contains(theFolder);
-    return false;
-  }
-
-  Config_DataModelReader* myXMLReader;
+  //QStringList listOfShowNotEmptyFolders(bool fromRoot = true) const;
+
+  //int getNumberOfFolderItems(const ModelAPI_Folder* theFolder) const;
+  //ObjectPtr getObjectInFolder(const ModelAPI_Folder* theFolder, int theId) const;
+
+  //VisibilityState getVisibilityState(const QModelIndex& theIndex) const;
+
+  //void addShownFolder(DocumentPtr theDoc, QString theFolder)
+  //{
+  //  if (!myShownFolders.contains(theDoc)) {
+  //    myShownFolders[theDoc] = QStringList();
+  //  }
+  //  myShownFolders[theDoc].append(theFolder);
+  //}
+
+  //void removeShownFolder(DocumentPtr theDoc, QString theFolder)
+  //{
+  //  if (myShownFolders.contains(theDoc)) {
+  //    myShownFolders[theDoc].removeAll(theFolder);
+  //    if (myShownFolders[theDoc].isEmpty())
+  //      myShownFolders.remove(theDoc);
+  //  }
+  //}
+
+  //bool hasShownFolder(DocumentPtr theDoc, QString theFolder) const
+  //{
+  //  if (myShownFolders.contains(theDoc))
+  //    return myShownFolders[theDoc].contains(theFolder);
+  //  return false;
+  //}
+
+  //Config_DataModelReader* myXMLReader;
 
   XGUI_Workshop* myWorkshop;
   QMap<DocumentPtr, QStringList> myShownFolders;
   //bool myIsEventsProcessingBlocked;
+
+  ModuleBase_ITreeNode* myRoot;
 };
 
 #endif
\ No newline at end of file
index cb58b56280d48cf46586c0145e64e3a99fe0a2eb..364153dcaf508a16d9e640cae364ef056d284429 100644 (file)
@@ -37,7 +37,7 @@
 #include <ModelAPI_Object.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_AttributeIntArray.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 
 #include <ModuleBase_BRepOwner.h>
 #include <ModuleBase_IModule.h>
@@ -292,7 +292,7 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer)
   if (aContext.IsNull())
     return aErased;
 
-  AISObjectPtr anObject = myResult2AISObjectMap[theObject];
+  AISObjectPtr anObject = myResult2AISObjectMap.value(theObject);
   if (anObject) {
     Handle(AIS_InteractiveObject) anAIS = anObject->impl<Handle(AIS_InteractiveObject)>();
     if (!anAIS.IsNull()) {
@@ -447,9 +447,8 @@ bool XGUI_Displayer::isVisible(XGUI_Displayer* theDisplayer, const ObjectPtr& th
     // compsolid is not visualized in the viewer,
     // but should have presentation when all sub solids are
     // visible. It is useful for highlight presentation where compsolid shape is selectable
-    if (!aVisible && aResult.get() && aResult->groupName() == ModelAPI_ResultCompSolid::group()) {
-      ResultCompSolidPtr aCompsolidResult =
-        std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
+    if (!aVisible && aResult.get() && aResult->groupName() == ModelAPI_ResultBody::group()) {
+      ResultBodyPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
       if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
         bool anAllSubsVisible = aCompsolidResult->numberOfSubs() > 0;
         for(int i = 0; i < aCompsolidResult->numberOfSubs() && anAllSubsVisible; i++) {
@@ -515,7 +514,7 @@ void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrsPtr>& theValue
       ObjectPtr anObject = aPrs->object();
       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
       if (aResult.get() && isVisible(aResult)) {
-        AISObjectPtr anObj = myResult2AISObjectMap[aResult];
+        AISObjectPtr anObj = myResult2AISObjectMap.value(aResult);
         Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
         if (!anAIS.IsNull()) {
           // The methods are replaced in order to provide multi-selection, e.g. restore selection
@@ -557,8 +556,8 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
   bool aErased = false;
   Handle(AIS_InteractiveContext) aContext = AISContext();
   if (!aContext.IsNull()) {
-    foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) {
-      AISObjectPtr aAISObj = myResult2AISObjectMap[aObj];
+    foreach (ObjectPtr aObj, myResult2AISObjectMap.objects()) {
+      AISObjectPtr aAISObj = myResult2AISObjectMap.value(aObj);
       // erase an object
       Handle(AIS_InteractiveObject) anIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
       if (!anIO.IsNull()) {
@@ -585,10 +584,7 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
 //**************************************************************
 AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const
 {
-  AISObjectPtr anIO;
-  if (myResult2AISObjectMap.contains(theObject))
-    anIO = myResult2AISObjectMap[theObject];
-  return anIO;
+  return myResult2AISObjectMap.value(theObject);
 }
 
 //**************************************************************
@@ -601,16 +597,7 @@ ObjectPtr XGUI_Displayer::getObject(const AISObjectPtr& theIO) const
 //**************************************************************
 ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) const
 {
-  ObjectPtr anObject;
-  ResultToAISMap::const_iterator aMapIter = myResult2AISObjectMap.cbegin();
-  for (; aMapIter != myResult2AISObjectMap.cend(); aMapIter++) {
-    const AISObjectPtr& aAIS = aMapIter.value();
-    Handle(AIS_InteractiveObject) anAIS = aAIS->impl<Handle(AIS_InteractiveObject)>();
-    if (anAIS == theIO)
-      anObject = aMapIter.key();
-    if (anObject.get())
-      break;
-  }
+  ObjectPtr anObject = myResult2AISObjectMap.value(theIO);
   if (!anObject.get()) {
     std::shared_ptr<GeomAPI_AISObject> anAISObj = AISObjectPtr(new GeomAPI_AISObject());
     if (!theIO.IsNull()) {
@@ -873,7 +860,7 @@ void XGUI_Displayer::removeFilters()
 //**************************************************************
 void XGUI_Displayer::showOnly(const QObjectPtrList& theList)
 {
-  QObjectPtrList aDispList = myResult2AISObjectMap.keys();
+  QObjectPtrList aDispList = myResult2AISObjectMap.objects();
   foreach(ObjectPtr aObj, aDispList) {
     if (!theList.contains(aObj))
       erase(aObj, false);
@@ -952,7 +939,7 @@ QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject,
 //**************************************************************
 void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS)
 {
-  myResult2AISObjectMap[theObject] = theAIS;
+  myResult2AISObjectMap.add(theObject, theAIS);
 
 #ifdef DEBUG_DISPLAY
   std::ostringstream aPtrStr;
@@ -967,8 +954,8 @@ void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS
 std::string XGUI_Displayer::getResult2AISObjectMapInfo() const
 {
   QStringList aContent;
-  foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) {
-    AISObjectPtr aAISObj = myResult2AISObjectMap[aObj];
+  foreach (ObjectPtr aObj, myResult2AISObjectMap.objects()) {
+    AISObjectPtr aAISObj = myResult2AISObjectMap.value(aObj);
     std::ostringstream aPtrStr;
     aPtrStr << "aObj = " << aObj.get() << ":";
     aPtrStr << "anAIS = " << aAISObj.get() << ":";
@@ -991,7 +978,7 @@ void XGUI_Displayer::getPresentations(const ObjectPtr& theObject,
     if (aAISObj.get() == NULL) {
       // if result is a result of a composite feature, it is visualized by visualization of
       // composite children, so we should get one of this presentations
-      ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
+      ResultBodyPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
       if (aCompSolid.get() && aCompSolid->numberOfSubs() > 0) {
         aAISObj = getAISObject(aCompSolid->subResult(0));
       }
index 025a6c368f98698457ed6f5b606f3c33722488f1..5da345d703014df4c315506532308ff7bcf6ebe8 100644 (file)
@@ -52,6 +52,116 @@ class XGUI_Workshop;
 class VInspectorAPI_CallBack;
 #endif
 
+
+class XGUI_TwoSidePresentationMap
+{
+public:
+  ~XGUI_TwoSidePresentationMap() { clear(); }
+
+  /// Add new values pair to the map
+  /// \param theObj an object
+  /// \param theAIS a corresponded presentation
+  bool add(const ObjectPtr& theObj, const AISObjectPtr& theAIS)
+  {
+    if (myResultToAISMap.contains(theObj))
+      return false;
+    Handle(AIS_InteractiveObject) anAIS = theAIS->impl<Handle(AIS_InteractiveObject)>();
+    myResultToAISMap[theObj] = anAIS;
+    myAIStoResultMap[anAIS] = theObj;
+    return true;
+  }
+
+  /// Removes values by object
+  /// \param theObj an object
+  bool remove(const ObjectPtr& theObj)
+  {
+    if (!myResultToAISMap.contains(theObj))
+      return false;
+    Handle(AIS_InteractiveObject) aAIS = myResultToAISMap[theObj];
+    myResultToAISMap.remove(theObj);
+    myAIStoResultMap.remove(aAIS);
+    return true;
+  }
+
+  /// Removes values by presentation
+  /// \param theAIS a presentation
+  bool remove(const AISObjectPtr& theAIS)
+  {
+    Handle(AIS_InteractiveObject) anAIS = theAIS->impl<Handle(AIS_InteractiveObject)>();
+    if (!myAIStoResultMap.contains(anAIS))
+      return false;
+    ObjectPtr aObj = myAIStoResultMap[anAIS];
+    myResultToAISMap.remove(aObj);
+    myAIStoResultMap.remove(anAIS);
+    return true;
+  }
+
+  /// Removes all values
+  void clear()
+  {
+    myResultToAISMap.clear();
+    myAIStoResultMap.clear();
+  }
+
+  /// Returns presentation by object
+  /// \param theObj an object
+  AISObjectPtr value(const ObjectPtr& theObj) const
+  {
+    if (myResultToAISMap.contains(theObj)) {
+      Handle(AIS_InteractiveObject) anAIS = myResultToAISMap[theObj];
+      AISObjectPtr anAISObj = AISObjectPtr(new GeomAPI_AISObject());
+      anAISObj->setImpl(new Handle(AIS_InteractiveObject)(anAIS));
+      return anAISObj;
+    }
+    return AISObjectPtr();
+  }
+
+  /// Returns object by presentation
+  /// \param theAIS a presentation
+  ObjectPtr value(const AISObjectPtr& theAIS) const
+  {
+    Handle(AIS_InteractiveObject) anAIS = theAIS->impl<Handle(AIS_InteractiveObject)>();
+    if (myAIStoResultMap.contains(anAIS))
+      return myAIStoResultMap[anAIS];
+    return ObjectPtr();
+  }
+
+  /// Returns object by presentation
+  /// \param theAIS a presentation
+  ObjectPtr value(const Handle(AIS_InteractiveObject)& theAIS) const
+  {
+    if (myAIStoResultMap.contains(theAIS))
+      return myAIStoResultMap[theAIS];
+    return ObjectPtr();
+  }
+
+  /// Returns number of values
+  int size() const { return myResultToAISMap.size(); }
+
+  /// Returns list of objects
+  QObjectPtrList objects() const { return myResultToAISMap.keys(); }
+
+  /// returns list of presentations
+  QList<Handle(AIS_InteractiveObject)> presentations() const { return myAIStoResultMap.keys(); }
+
+  /// Returns true if the Map contains the object
+  /// \param theObj an object
+  bool contains(const ObjectPtr& theObj) const { return myResultToAISMap.contains(theObj); }
+
+  /// Returns true if the Map contains the presentation
+  /// \param theAIS a presentation
+  bool contains(const AISObjectPtr& theAIS) const
+  {
+    Handle(AIS_InteractiveObject) anAIS = theAIS->impl<Handle(AIS_InteractiveObject)>();
+    return myAIStoResultMap.contains(anAIS);
+  }
+
+private:
+  QMap<ObjectPtr, Handle(AIS_InteractiveObject)> myResultToAISMap;
+  QMap<Handle(AIS_InteractiveObject), ObjectPtr> myAIStoResultMap;
+};
+
+
 /**\class XGUI_Displayer
  * \ingroup GUI
  * \brief Displayer. Provides mechanizm of display/erase of objects in the viewer
@@ -206,10 +316,13 @@ class XGUI_EXPORT XGUI_Displayer: public QObject
   int objectsCount() const { return myResult2AISObjectMap.size(); }
 
   /// Returns list of displayed objects
-  QObjectPtrList displayedObjects() const { return myResult2AISObjectMap.keys(); }
+  QObjectPtrList displayedObjects() const { return myResult2AISObjectMap.objects(); }
 
   /// Returns list of displayed objects
-  QList<AISObjectPtr> displayedPresentations() const { return myResult2AISObjectMap.values(); }
+  QList<Handle(AIS_InteractiveObject)> displayedPresentations() const
+  {
+    return myResult2AISObjectMap.presentations();
+  }
 
   /// Returns true if the given object can be shown in shaded mode
   /// \param theObject object to check
@@ -326,8 +439,7 @@ protected:
   GeomCustomPrsPtr myCustomPrs;
 
   /// Definition of a type of map which defines correspondance between objects and presentations
-  typedef QMap<ObjectPtr, AISObjectPtr> ResultToAISMap;
-  ResultToAISMap myResult2AISObjectMap; ///< A map of displayed objects
+  XGUI_TwoSidePresentationMap myResult2AISObjectMap; ///< A map of displayed objects
 
   /// Number of blocking of the viewer update. The viewer is updated only if it is zero
   int myViewerBlockedRecursiveCount;
index 4f2130509984d134c0c2bf2190fe2b48febe0670..5c67a3d5037b62d454236c5de5ec2b8b403b1c11 100644 (file)
@@ -109,6 +109,13 @@ AISObjectPtr XGUI_ModuleConnector::findPresentation(const ObjectPtr& theObject)
   return aDisp->getAISObject(theObject);
 }
 
+bool XGUI_ModuleConnector::isVisible(const ObjectPtr& theObject) const
+{
+  XGUI_Displayer* aDisp = myWorkshop->displayer();
+  return aDisp->isVisible(theObject);
+}
+
+
 ObjectPtr XGUI_ModuleConnector::findPresentedObject(const AISObjectPtr& theAIS) const
 {
   XGUI_Displayer* aDisp = myWorkshop->displayer();
index 6bf3914c29d3656eee583281953927fe99e97c4f..409c6edee4eb305688782e69a30dfc2afd0979bc 100644 (file)
@@ -94,6 +94,10 @@ Q_OBJECT
   //! Returns data object by AIS
   virtual ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const;
 
+  //! Returns true if the object is displayed
+  //! \param theObject a data object
+  virtual bool isVisible(const ObjectPtr& theObject) const;
+
   //! Select features clearing previous selection.
   //! If the list is empty then selection will be cleared
   virtual void setSelected(const QList<std::shared_ptr<ModuleBase_ViewerPrs>>& theValues);
index d256e56dba733e6704d73550683ba4d21846cb25..ff78af48c690c2d2d75583af8521b41975f03f12 100644 (file)
@@ -25,7 +25,6 @@
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Document.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_Tools.h>
 
 #include <ModuleBase_Tools.h>
@@ -220,7 +219,6 @@ void XGUI_DataTree::processHistoryChange(const QModelIndex& theIndex)
     aDoc->setCurrentFeature(FeaturePtr(), true);
     aMgr->finishOperation();
   }
-  QModelIndex aNewIndex = aModel->lastHistoryIndex();
   QModelIndex aParent = theIndex.parent();
   int aSize = aModel->rowCount(aParent);
   for (int i = 0; i < aSize; i++) {
@@ -426,9 +424,10 @@ XGUI_ObjectsBrowser::~XGUI_ObjectsBrowser()
 {
 }
 
-void XGUI_ObjectsBrowser::setXMLReader(Config_DataModelReader* theReader)
+void XGUI_ObjectsBrowser::initialize(ModuleBase_ITreeNode* theRoot)
 {
-  myDocModel->setXMLReader(theReader);
+  //myDocModel->setXMLReader(theReader);
+  myDocModel->setRoot(theRoot);
   myTreeView->setModel(myDocModel);
 
   // It has to be done after setting of model
@@ -606,7 +605,8 @@ void XGUI_ObjectsBrowser::onBeforeReset()
 void XGUI_ObjectsBrowser::onAfterModelReset()
 {
   foreach(QModelIndex aIndex, myExpandedItems) {
-    myTreeView->setExpanded(aIndex, true);
+    if (myTreeView->dataModel()->hasIndex(aIndex))
+      myTreeView->setExpanded(aIndex, true);
   }
 }
 
@@ -646,9 +646,10 @@ void XGUI_ObjectsBrowser::updateAllIndexes(int theColumn, const QModelIndex& the
   int aNb = myDocModel->rowCount(theParent);
   for (int i = 0; i < aNb; i++) {
     QModelIndex aIdx = myDocModel->index(i, theColumn, theParent);
-    if (aIdx.isValid()) {
+    if (aIdx.isValid() && myDocModel->hasIndex(aIdx)) {
       myTreeView->update(aIdx);
-      updateAllIndexes(theColumn, aIdx);
+      if (myTreeView->isExpanded(aIdx))
+        updateAllIndexes(theColumn, aIdx);
     }
   }
 }
index f83ddfcadfc13583265d06c6036755b9ab053ab9..c0507306554db1acea9b123afedfcdf72bf7e576 100644 (file)
@@ -37,6 +37,7 @@ class ModuleBase_IDocumentDataModel;
 class XGUI_DataModel;
 class Config_DataModelReader;
 class XGUI_Workshop;
+class ModuleBase_ITreeNode;
 
 //#define DEBUG_INDXES
 
@@ -175,7 +176,10 @@ Q_OBJECT
   //! Returns currently selected indexes
   QModelIndexList selectedIndexes() const
   {
-    return myTreeView->selectionModel()->selectedIndexes();
+    if (myTreeView->selectionModel())
+      return myTreeView->selectionModel()->selectedIndexes();
+    else
+      return QModelIndexList();
   }
 
   //! Returns TreeView widget
@@ -193,9 +197,8 @@ Q_OBJECT
   /// Resets the object browser into initial state
   void clearContent();
 
-  /// Set XML reader object for data model
-  /// \param theReader the reader object
-  void setXMLReader(Config_DataModelReader* theReader);
+  /// Initialize the Object browser
+  void initialize(ModuleBase_ITreeNode* theRoot);
 
   /// Returns list of folders opened state for the given document
   /// \param theDoc the document
index 04db48853ad3f483eeaf90843f637c69f7a3cf5e..3073bf450d83146ead97e6151fff677a75850fc2 100644 (file)
@@ -31,7 +31,7 @@
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Session.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
 
 #include <AIS_InteractiveContext.hxx>
@@ -264,7 +264,7 @@ void XGUI_Selection::fillPresentation(ModuleBase_ViewerPrsPtr& thePrs,
     // is On and we have to use parent result which corresponds to the CompSolid shape
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aFeature);
     if (aResult.get()) {
-      ResultCompSolidPtr aCompSolid = ModelAPI_Tools::compSolidOwner(aResult);
+      ResultBodyPtr aCompSolid = ModelAPI_Tools::bodyOwner(aResult);
       if (aCompSolid.get()) {
         GeomShapePtr aShape = aCompSolid->shape();
         if (aShape.get() && aShape->isEqual(thePrs->shape())) {
index bece087dc5f4266476d175da5814030859875d1f..5c42eb18923dbd16a6731c9fadb2effa4956eae6 100755 (executable)
@@ -38,7 +38,8 @@
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Result.h>
 #include <ModelAPI_Object.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_Tools.h>
 
 #include <ModuleBase_ViewerPrs.h>
 #include <ModuleBase_Tools.h>
@@ -97,38 +98,32 @@ void XGUI_SelectionMgr::setSelectedOwners(const SelectMgr_IndexedMapOfOwner& the
 void XGUI_SelectionMgr::onObjectBrowserSelection()
 {
   QList<ModuleBase_ViewerPrsPtr> aSelectedPrs =
-             myWorkshop->selector()->selection()->getSelected(ModuleBase_ISelection::Browser);
-
-  QList<ModuleBase_ViewerPrsPtr> aTmpList = aSelectedPrs;
-  ObjectPtr aObject;
-  FeaturePtr aFeature;
-  foreach(ModuleBase_ViewerPrsPtr aPrs, aTmpList) {
-    aObject = aPrs->object();
-    if (aObject.get()) {
-      aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
-      if (aFeature.get()) {
-        const std::list<std::shared_ptr<ModelAPI_Result>> aResList = aFeature->results();
-        ResultPtr aResult;
-        ResultCompSolidPtr aCompSolid;
-        std::list<ResultPtr>::const_iterator aIt;
-        for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
-          aResult = (*aIt);
+    myWorkshop->selector()->selection()->getSelected(ModuleBase_ISelection::Browser);
+  XGUI_Displayer* aDisplayer = myWorkshop->displayer();
+  if (!myWorkshop->operationMgr()->hasOperation()) {
+
+    QList<ModuleBase_ViewerPrsPtr> aTmpList = aSelectedPrs;
+    ObjectPtr aObject;
+    FeaturePtr aFeature;
+    // Select all results of a selected feature in viewer
+    foreach(ModuleBase_ViewerPrsPtr aPrs, aSelectedPrs) {
+      aObject = aPrs->object();
+      if (aObject.get()) {
+        aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
+        if (aFeature.get()) {
+        std::list<ResultPtr> allRes;
+        ModelAPI_Tools::allResults(aFeature, allRes);
+        for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
           aSelectedPrs.append(std::shared_ptr<ModuleBase_ViewerPrs>(
-            new ModuleBase_ViewerPrs(aResult, GeomShapePtr(), NULL)));
-          aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
-          if (aCompSolid.get()) {
-            for (int i = 0; i < aCompSolid->numberOfSubs(); i++) {
-              ResultBodyPtr aResult = aCompSolid->subResult(i);
-              aSelectedPrs.append(std::shared_ptr<ModuleBase_ViewerPrs>(
-                new ModuleBase_ViewerPrs(aResult, aResult->shape(), NULL)));
-            }
+            new ModuleBase_ViewerPrs(*aRes, GeomShapePtr(), NULL)));
           }
         }
       }
     }
+    aDisplayer->setSelected(aTmpList);
+  } else {
+    aDisplayer->setSelected(aSelectedPrs);
   }
-  XGUI_Displayer* aDisplayer = myWorkshop->displayer();
-  aDisplayer->setSelected(aSelectedPrs);
   emit selectionChanged();
 }
 
index 6ca6f7d50f1ce7ead8f2c81bc5050910fccdbd13..fc533769bd878a01d4cf149abc6f01a731db854a 100755 (executable)
@@ -72,7 +72,6 @@
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Object.h>
 #include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultParameter.h>
@@ -1352,7 +1351,7 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent)
   aObjDock->setStyleSheet(
       "::title { position: relative; padding-left: 5px; text-align: left center }");
   myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock, this);
-  myObjectBrowser->setXMLReader(myDataModelXMLReader);
+  myObjectBrowser->initialize(myModule->rootNode());
   myModule->customizeObjectBrowser(myObjectBrowser);
   aObjDock->setWidget(myObjectBrowser);
 
@@ -1488,8 +1487,9 @@ void XGUI_Workshop::hidePanel(QDockWidget* theDockWidget)
 //******************************************************
 void XGUI_Workshop::showObjectBrowser()
 {
-  if (!isSalomeMode())
+  if (!isSalomeMode()) {
     myObjectBrowser->parentWidget()->show();
+  }
 }
 
 //******************************************************
@@ -1680,18 +1680,20 @@ bool XGUI_Workshop::prepareForDisplay(const std::set<ObjectPtr>& theObjects) con
   for (std::set<ObjectPtr>::const_iterator anObjectsIt = theObjects.begin();
     anObjectsIt != theObjects.end(); anObjectsIt++) {
     ObjectPtr anObject = *anObjectsIt;
-    ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(anObject);
+    ResultBodyPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anObject);
     if (aCompRes.get()) {
-      if (aCompRes->numberOfSubs(true) == 0)
+      std::list<ResultPtr> allRes;
+      ModelAPI_Tools::allSubs(aCompRes, allRes);
+      if (allRes.empty()) {
         anAllProcessedObjects.insert(anObject);
-      else {
-        for (int i = 0; i < aCompRes->numberOfSubs(true); i++) {
-          ResultPtr aSubRes = aCompRes->subResult(i, true);
-          anAllProcessedObjects.insert(aCompRes->subResult(i, true));
+      } else {
+        for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+          ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRes);
+          if (aBody.get() && aBody->numberOfSubs() == 0)
+            anAllProcessedObjects.insert(aBody);
         }
       }
-    }
-    else
+    } else
       anAllProcessedObjects.insert(anObject);
   }
 
@@ -2124,11 +2126,14 @@ bool XGUI_Workshop::canBeShaded(const ObjectPtr& theObject) const
 {
   bool aCanBeShaded = myDisplayer->canBeShaded(theObject);
   if (!aCanBeShaded) {
-    ResultCompSolidPtr aCompsolidResult =
-                std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
-    if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
-      for(int i = 0; i < aCompsolidResult->numberOfSubs() && !aCanBeShaded; i++)
-        aCanBeShaded = myDisplayer->canBeShaded(aCompsolidResult->subResult(i));
+    ResultBodyPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theObject);
+    if (aCompRes.get() != NULL) { // change colors for all sub-solids
+      std::list<ResultPtr> allRes;
+      ModelAPI_Tools::allSubs(aCompRes, allRes);
+      std::list<ResultPtr>::iterator aRes = allRes.begin();
+      for(; aRes != allRes.end() && !aCanBeShaded; aRes++) {
+        aCanBeShaded = myDisplayer->canBeShaded(*aRes);
+      }
     }
   }
   return aCanBeShaded;
@@ -2225,12 +2230,12 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
   foreach(ObjectPtr anObj, theObjects) {
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
     if (aResult.get() != NULL) {
-      ResultCompSolidPtr aCompsolidResult =
-        std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
-      if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
-        for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
-          setColor(aCompsolidResult->subResult(i), !isRandomColor ? aColorResult :
-                                                                    aDlg->getRandomColor());
+      ResultBodyPtr aBodyResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
+      if (aBodyResult.get() != NULL) { // change colors for all sub-solids
+        std::list<ResultPtr> allRes;
+        ModelAPI_Tools::allSubs(aBodyResult, allRes);
+        for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+          setColor(*aRes, !isRandomColor ? aColorResult : aDlg->getRandomColor());
         }
       }
       setColor(aResult, !isRandomColor ? aColorResult : aDlg->getRandomColor());
@@ -2268,11 +2273,12 @@ void setTransparency(double theTransparency, const QObjectPtrList& theObjects)
   foreach(ObjectPtr anObj, theObjects) {
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
     if (aResult.get() != NULL) {
-      ResultCompSolidPtr aCompsolidResult =
-        std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
-      if (aCompsolidResult.get() != NULL) { // change property for all sub-solids
-        for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
-          setTransparency(aCompsolidResult->subResult(i), theTransparency);
+      ResultBodyPtr aBodyResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
+      if (aBodyResult.get() != NULL) { // change property for all sub-solids
+        std::list<ResultPtr> allRes;
+        ModelAPI_Tools::allSubs(aBodyResult, allRes);
+        for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+          setTransparency(*aRes, theTransparency);
         }
       }
       setTransparency(aResult, theTransparency);
@@ -2328,11 +2334,12 @@ void XGUI_Workshop::changeDeflection(const QObjectPtrList& theObjects)
   foreach(ObjectPtr anObj, theObjects) {
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
     if (aResult.get() != NULL) {
-      ResultCompSolidPtr aCompsolidResult =
-        std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
-      if (aCompsolidResult.get() != NULL) { // change property for all sub-solids
-        for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
-          setDeflection(aCompsolidResult->subResult(i), aDeflection);
+      ResultBodyPtr aBodyResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
+      if (aBodyResult.get() != NULL) { // change property for all sub-solids
+        std::list<ResultPtr> allRes;
+        ModelAPI_Tools::allSubs(aBodyResult, allRes);
+        for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+          setDeflection(*aRes, aDeflection);
         }
       }
       setDeflection(aResult, aDeflection);
@@ -2515,14 +2522,15 @@ void XGUI_Workshop::displayGroupResults(DocumentPtr theDoc, std::string theGroup
 //**************************************************************
 void XGUI_Workshop::setDisplayMode(const QObjectPtrList& theList, int theMode)
 {
-  foreach(ObjectPtr aObj, theList) {
-    myDisplayer->setDisplayMode(aObj, (XGUI_Displayer::DisplayMode)theMode, false);
+  foreach(ObjectPtr anObj, theList) {
+    myDisplayer->setDisplayMode(anObj, (XGUI_Displayer::DisplayMode)theMode, false);
 
-    ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aObj);
-    if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
-      for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
-          myDisplayer->setDisplayMode(aCompsolidResult->subResult(i),
-                                      (XGUI_Displayer::DisplayMode)theMode, false);
+    ResultBodyPtr aBodyResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anObj);
+    if (aBodyResult.get() != NULL) { // change display mode for all sub-solids
+      std::list<ResultPtr> allRes;
+      ModelAPI_Tools::allSubs(aBodyResult, allRes);
+      for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+        myDisplayer->setDisplayMode(*aRes, (XGUI_Displayer::DisplayMode)theMode, false);
       }
     }
   }
index 4b3546211d2f1b4d540f3f01eb507b029daa91c2..f7720512d9fc73e38d1df1ff9d9458ab63063735 100755 (executable)
@@ -38,7 +38,6 @@
 #include <ModelAPI_Result.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Data.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_Tools.h>
 
 #include <ModuleBase_Events.h>
index dadc9d953e52076dc434e5f7b46891a5b3676173..bf8617124fa8aded48247d0aab88f09e69899a64 100644 (file)
@@ -163,21 +163,35 @@ Face_13 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_7/Wire-Sket
 # Shells
 Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")])
 Shell_1.result().setName("Shell_1_1")
-Shell_2 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")])
+model.addRecover(Part_1_doc, Shell_1, [Face_10.result()])
+model.addRecover(Part_1_doc, Shell_1, [Face_11.result()])
+Shell_2 = model.addShell(Part_1_doc, [model.selection("FACE", "Recover_1_1"), model.selection("FACE", "Recover_2_1")])
 Shell_2.result().setName("Shell_2_1")
-Shell_3 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")])
+model.addRecover(Part_1_doc, Shell_1, [Face_10.result()])
+model.addRecover(Part_1_doc, Shell_1, [Face_11.result()])
+Shell_3 = model.addShell(Part_1_doc, [model.selection("FACE", "Recover_3_1"), model.selection("FACE", "Recover_4_1")])
 Shell_3.result().setName("Shell_3_1")
-Shell_4 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")])
+model.addRecover(Part_1_doc, Shell_1, [Face_10.result()])
+model.addRecover(Part_1_doc, Shell_1, [Face_11.result()])
+Shell_4 = model.addShell(Part_1_doc, [model.selection("FACE", "Recover_5_1"), model.selection("FACE", "Recover_6_1")])
 Shell_4.result().setName("Shell_4_1")
-Shell_5 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")])
+model.addRecover(Part_1_doc, Shell_1, [Face_10.result()])
+model.addRecover(Part_1_doc, Shell_1, [Face_11.result()])
+Shell_5 = model.addShell(Part_1_doc, [model.selection("FACE", "Recover_7_1"), model.selection("FACE", "Recover_8_1")])
 Shell_5.result().setName("Shell_5_1")
 Shell_6 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_12_1"), model.selection("FACE", "Face_13_1")])
 Shell_6.result().setName("Shell_6_1")
-Shell_7 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_12_1"), model.selection("FACE", "Face_13_1")])
+model.addRecover(Part_1_doc, Shell_1, [Face_12.result()])
+model.addRecover(Part_1_doc, Shell_1, [Face_13.result()])
+Shell_7 = model.addShell(Part_1_doc, [model.selection("FACE", "Recover_9_1"), model.selection("FACE", "Recover_10_1")])
 Shell_7.result().setName("Shell_7_1")
-Shell_8 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")])
+model.addRecover(Part_1_doc, Shell_1, [Face_10.result()])
+model.addRecover(Part_1_doc, Shell_1, [Face_11.result()])
+Shell_8 = model.addShell(Part_1_doc, [model.selection("FACE", "Recover_11_1"), model.selection("FACE", "Recover_12_1")])
 Shell_8.result().setName("Shell_8_1")
-Shell_9 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")])
+model.addRecover(Part_1_doc, Shell_1, [Face_10.result()])
+model.addRecover(Part_1_doc, Shell_1, [Face_11.result()])
+Shell_9 = model.addShell(Part_1_doc, [model.selection("FACE", "Recover_13_1"), model.selection("FACE", "Recover_14_1")])
 Shell_9.result().setName("Shell_9_1")
 
 # Parameters
@@ -516,16 +530,16 @@ model.testHaveNamingFaces(Translation_90, model, Part_1_doc)
 
 
 model.testNbResults(Translation_48, 0)
-assert(Translation_48.feature().error() == 'Attribute "axis_object" is not initialized.')
+assert(Translation_48.feature().error() == 'Translation axis is not selected.')
 
 model.testNbResults(Translation_57, 0)
-assert(Translation_57.feature().error() == 'Attribute "axis_object" is not initialized.')
+assert(Translation_57.feature().error() == 'Translation axis is not selected.')
 
 model.testNbResults(Translation_66, 0)
-assert(Translation_66.feature().error() == 'Attribute "axis_object" is not initialized.')
+assert(Translation_66.feature().error() == 'Translation axis is not selected.')
 
 model.testNbResults(Translation_75, 0)
-assert(Translation_75.feature().error() == 'Attribute "axis_object" is not initialized.')
+assert(Translation_75.feature().error() == 'Translation axis is not selected.')
 
 model.testNbResults(Translation_84, 0)
-assert(Translation_84.feature().error() == 'Attribute "axis_object" is not initialized.')
\ No newline at end of file
+assert(Translation_84.feature().error() == 'Translation axis is not selected.')