Salome HOME
Issue #3221: Set gray color for disabled features
[modules/shaper.git] / src / ModelAPI / ModelAPI_Tools.cpp
index 0c312f3955c162af9e8bbc0ddeb993efa422d02e..2f87922c2c277aea736198a3391fbd4ec0a28d14 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2020  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
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultParameter.h>
 #include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_AttributeDocRef.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_AttributeBoolean.h>
 #include <list>
 #include <map>
 #include <iostream>
 #include <sstream>
 
 #include <Events_Loop.h>
+#include <Locale_Convert.h>
 #include <ModelAPI_Events.h>
 
+#include <GeomAPI_ShapeHierarchy.h>
+#include <GeomAPI_ShapeIterator.h>
+
 #define RECURSE_TOP_LEVEL 50
 
 //#define DEBUG_REMOVE_FEATURES
@@ -167,9 +173,10 @@ std::string getFeatureError(const FeaturePtr& theFeature)
 ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGroup,
                        const std::string& theName)
 {
+  std::wstring aName = Locale::Convert::toWString(theName);
   for (int anIndex = 0; anIndex < theDocument->size(theGroup); ++anIndex) {
     ObjectPtr anObject = theDocument->object(theGroup, anIndex);
-    if (anObject->data()->name() == theName)
+    if (anObject->data()->name() == aName)
       return anObject;
   }
   // not found
@@ -333,9 +340,9 @@ void allResults(const FeaturePtr& theFeature, std::list<ResultPtr>& theResults)
 }
 
 //******************************************************************
-bool allDocumentsActivated(std::string& theNotActivatedNames)
+bool allDocumentsActivated(std::wstring& theNotActivatedNames)
 {
-  theNotActivatedNames = "";
+  theNotActivatedNames = L"";
   bool anAllPartActivated = true;
 
   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
@@ -346,7 +353,7 @@ bool allDocumentsActivated(std::string& theNotActivatedNames)
     if (!aPart->isActivated()) {
       anAllPartActivated = false;
       if (!theNotActivatedNames.empty())
-        theNotActivatedNames += ", ";
+        theNotActivatedNames += L", ";
       theNotActivatedNames += aObject->data()->name().c_str();
     }
   }
@@ -354,7 +361,7 @@ bool allDocumentsActivated(std::string& theNotActivatedNames)
 }
 
 bool removeFeaturesAndReferences(const std::set<FeaturePtr>& theFeatures,
-                                 const bool theFlushRedisplay,
+                                 const bool /*theFlushRedisplay*/,
                                  const bool theUseComposite,
                                  const bool theUseRecursion)
 {
@@ -464,10 +471,10 @@ void findReferences(const std::set<FeaturePtr>& theFeatures,
       }
       else { // filter references to skip composition features of the current feature
         std::set<FeaturePtr> aFilteredFeatures;
-        std::set<FeaturePtr>::const_iterator anIt = aSelRefFeatures.begin(),
-                                             aLast = aSelRefFeatures.end();
-        for (; anIt != aLast; anIt++) {
-          FeaturePtr aCFeature = *anIt;
+        std::set<FeaturePtr>::const_iterator aRefIt = aSelRefFeatures.begin(),
+                                             aRefLast = aSelRefFeatures.end();
+        for (; aRefIt != aRefLast; aRefIt++) {
+          FeaturePtr aCFeature = *aRefIt;
           CompositeFeaturePtr aComposite =
             std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCFeature);
           if (aComposite.get() && aComposite->isSub(aFeature))
@@ -538,7 +545,7 @@ void findAllReferences(const std::set<FeaturePtr>& theFeatures,
     aResultRefList.insert(aMainRefList.begin(), aMainRefList.end());
     for (; anIt != aLast; anIt++) {
       FeaturePtr aFeature = *anIt;
-      int aRecLevel = 0;
+      aRecLevel = 0;
 #ifdef DEBUG_REMOVE_FEATURES_RECURSE
       std::cout << " Ref: " << getFeatureInfo(aFeature) << std::endl;
 #endif
@@ -610,7 +617,7 @@ void getConcealedResults(const FeaturePtr& theFeature,
   }
 }
 
-std::pair<std::string, bool> getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
+std::pair<std::wstring, bool> getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
                                             const bool theInherited)
 {
   typedef std::list< std::pair < std::string, std::list<ObjectPtr> > > ListOfReferences;
@@ -622,10 +629,10 @@ std::pair<std::string, bool> getDefaultName(const std::shared_ptr<ModelAPI_Resul
     // 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;
+    std::wostringstream aDefaultName;
     aDefaultName << getDefaultName(anOwnerRes).first;
     aDefaultName << "_" << (bodyIndex(theResult) + 1);
-    return std::pair<std::string, bool>(aDefaultName.str(), false);
+    return std::pair<std::wstring, bool>(aDefaultName.str(), false);
   }
 
   FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner());
@@ -646,6 +653,7 @@ std::pair<std::string, bool> getDefaultName(const std::shared_ptr<ModelAPI_Resul
         // 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().get() &&
                       aRefIt->second.front()->groupName() == ModelAPI_ResultBody::group());
         if (isBody && (isMainArg || aFoundRef == aReferences.end() ||
             aData->isPrecedingAttribute(aRefIt->first, aFoundRef->first)))
@@ -700,7 +708,7 @@ std::pair<std::string, bool> getDefaultName(const std::shared_ptr<ModelAPI_Resul
       // return name of reference result only if it has been renamed by the user,
       // in other case compose a default name
       if (anObjRes->data()->hasUserDefinedName()) {
-        std::stringstream aName;
+        std::wstringstream aName;
         aName << anObjRes->data()->name();
         std::map<ResultPtr, int>::iterator aFound = aNbRefToObject.find(anObjRes);
         if (aFound != aNbRefToObject.end()) {
@@ -708,19 +716,19 @@ std::pair<std::string, bool> getDefaultName(const std::shared_ptr<ModelAPI_Resul
           // referring to the same shape
           aName << "_" << aFound->second + 1;
         }
-        return std::pair<std::string, bool>(aName.str(), true);
+        return std::pair<std::wstring, bool>(aName.str(), true);
       }
     }
   }
 
   // compose default name by the name of the feature and the index of result
-  std::stringstream aDefaultName;
+  std::wstringstream aDefaultName;
   aDefaultName << anOwner->name();
   // if there are several results (issue #899: any number of result),
   // add unique prefix starting from second
   if (anIndexInOwner > 0 || theResult->groupName() == ModelAPI_ResultBody::group())
     aDefaultName << "_" << anIndexInOwner + 1;
-  return std::pair<std::string, bool>(aDefaultName.str(), false);
+  return std::pair<std::wstring, bool>(aDefaultName.str(), false);
 }
 
 std::set<FeaturePtr> getParents(const FeaturePtr& theFeature)
@@ -763,6 +771,21 @@ std::set<FeaturePtr> getParents(const FeaturePtr& theFeature)
   return aParents;
 }
 
+void fillShapeHierarchy(const GeomShapePtr& theShape,
+                        const ResultPtr& theContext,
+                        GeomAPI_ShapeHierarchy& theHierarchy)
+{
+  ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(theContext);
+  if (aResCompSolidPtr.get()) {
+    std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
+    if (aContextShape->shapeType() <= GeomAPI_Shape::COMPSOLID) {
+      theHierarchy.addParent(theShape, aContextShape);
+      fillShapeHierarchy(aContextShape, aResCompSolidPtr, theHierarchy);
+    }
+  }
+}
+
+
 void removeResults(const std::list<ResultPtr>& theResults)
 {
   // collect all documents where the results must be removed
@@ -786,6 +809,8 @@ void removeResults(const std::list<ResultPtr>& theResults)
   }
 }
 
+// used by GUI only
+// LCOV_EXCL_START
 
 //**************************************************************
 void setDeflection(ResultPtr theResult, const double theDeflection)
@@ -799,8 +824,6 @@ void setDeflection(ResultPtr theResult, const double theDeflection)
   }
 }
 
-// used by GUI only
-// LCOV_EXCL_START
 double getDeflection(const std::shared_ptr<ModelAPI_Result>& theResult)
 {
   double aDeflection = -1;
@@ -850,23 +873,31 @@ void getColor(const std::shared_ptr<ModelAPI_Result>& theResult, std::vector<int
 }
 
 //******************************************************
-void getIsoLines(const std::shared_ptr<ModelAPI_Result>& theResult, std::vector<int>& theNbLines)
+void getIsoLines(const std::shared_ptr<ModelAPI_Result>& theResult,
+  bool& isVisible, std::vector<int>& theNbLines)
 {
   theNbLines.clear();
+  isVisible = false;
+  if (!theResult.get())
+    return;
   if (theResult->groupName() == ModelAPI_ResultConstruction::group()) {
     theNbLines.push_back(0);
     theNbLines.push_back(0);
   }
   else {
     // get color from the attribute of the result
-    if (theResult.get() != NULL &&
-      theResult->data()->attribute(ModelAPI_Result::ISO_LINES_ID()).get() != NULL) {
-      AttributeIntArrayPtr aAttr = theResult->data()->intArray(ModelAPI_Result::ISO_LINES_ID());
-      if (aAttr.get() && aAttr->size()) {
+    AttributeIntArrayPtr aAttr = theResult->data()->intArray(ModelAPI_Result::ISO_LINES_ID());
+    if (aAttr.get()) {
+      if (aAttr->size()) {
         theNbLines.push_back(aAttr->value(0));
         theNbLines.push_back(aAttr->value(1));
       }
     }
+    AttributeBooleanPtr aBoolAttr =
+      theResult->data()->boolean(ModelAPI_Result::SHOW_ISO_LINES_ID());
+    if (aBoolAttr.get()) {
+      isVisible = aBoolAttr->value();
+    }
   }
 }
 
@@ -886,6 +917,31 @@ void setIsoLines(ResultPtr theResult, const std::vector<int>& theIso)
   }
 }
 
+//******************************************************
+void showIsoLines(std::shared_ptr<ModelAPI_Result> theResult, bool theShow)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_ISO_LINES_ID());
+  if (aAttr.get() != NULL) {
+    aAttr->setValue(theShow);
+  }
+}
+
+//******************************************************
+bool isShownIsoLines(std::shared_ptr<ModelAPI_Result> theResult)
+{
+  if (!theResult.get())
+    return false;
+
+  AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_ISO_LINES_ID());
+  if (aAttr.get() != NULL) {
+    return aAttr->value();
+  }
+  return false;
+}
+
 //**************************************************************
 void setTransparency(ResultPtr theResult, double theTransparency)
 {
@@ -911,7 +967,6 @@ double getTransparency(const std::shared_ptr<ModelAPI_Result>& theResult)
   }
   return aTransparency;
 }
-// LCOV_EXCL_STOP
 
 void copyVisualizationAttrs(
   std::shared_ptr<ModelAPI_Result> theSource, std::shared_ptr<ModelAPI_Result> theDest)
@@ -954,4 +1009,101 @@ void copyVisualizationAttrs(
   }
 }
 
+std::list<FeaturePtr> referencedFeatures(
+  std::shared_ptr<ModelAPI_Result> theTarget, const std::string& theFeatureKind,
+  const bool theSortResults)
+{
+  std::set<FeaturePtr> aResSet; // collect in the set initially to avoid duplicates
+  std::list<ResultPtr> allSubRes;
+  allSubRes.push_back(theTarget);
+  ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theTarget);
+  if (aBody.get())
+    allSubs(aBody, allSubRes);
+  std::list<ResultPtr>::iterator aSub = allSubRes.begin();
+  for(; aSub != allSubRes.end(); aSub++) {
+    const std::set<AttributePtr>& aRefs = (*aSub)->data()->refsToMe();
+    std::set<AttributePtr>::const_iterator aRef = aRefs.cbegin();
+    for(; aRef != aRefs.cend(); aRef++) {
+      FeaturePtr aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+      if (aFeat.get() && (theFeatureKind.empty() || aFeat->getKind() == theFeatureKind))
+        aResSet.insert(aFeat);
+    }
+  }
+  // add also feature of the target that may be referenced as a whole
+  FeaturePtr aTargetFeature = theTarget->document()->feature(theTarget);
+  const std::set<AttributePtr>& aRefs = aTargetFeature->data()->refsToMe();
+  std::set<AttributePtr>::const_iterator aRef = aRefs.cbegin();
+  for(; aRef != aRefs.cend(); aRef++) {
+    FeaturePtr aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+    if (aFeat.get() && (theFeatureKind.empty() || aFeat->getKind() == theFeatureKind))
+      aResSet.insert(aFeat);
+  }
+  // check also Group-operations that may refer to groups - add them for theFeatureKind "Group"
+  if (theFeatureKind == "Group") {
+    std::set<FeaturePtr> aGroupOperations;
+    for(bool aNeedIterate = true; aNeedIterate; ) {
+      std::set<FeaturePtr>::iterator aResIter = aResSet.begin();
+      for(; aResIter != aResSet.end(); aResIter++) {
+        std::list<ResultPtr>::const_iterator aGroupRes = (*aResIter)->results().cbegin();
+        for(; aGroupRes != (*aResIter)->results().cend(); aGroupRes++) {
+          const std::set<AttributePtr>& aGroupRefs = (*aGroupRes)->data()->refsToMe();
+          std::set<AttributePtr>::const_iterator aRefIt = aGroupRefs.cbegin();
+          for(; aRefIt != aGroupRefs.cend(); aRefIt++) {
+            FeaturePtr aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
+            if (aFeat.get() && !aGroupOperations.count(aFeat) && !aFeat->results().empty() &&
+                aFeat->firstResult()->groupName() == ModelAPI_ResultGroup::group()) {
+              // iterate results of this group operation because it may be without theTarget shape
+              GeomShapePtr aTargetShape = theTarget->shape();
+              bool anIsIn = false;
+              std::list<ResultPtr>::const_iterator anOpRes = aFeat->results().cbegin();
+              for(; anOpRes != aFeat->results().cend() && !anIsIn; anOpRes++) {
+                GeomShapePtr anOpShape = (*anOpRes)->shape();
+                if (!anOpShape.get() || anOpShape->isNull())
+                  continue;
+                for(GeomAPI_ShapeIterator aSubIt(anOpShape); aSubIt.more(); aSubIt.next()) {
+                  if (aTargetShape->isSubShape(aSubIt.current(), false)) {
+                    anIsIn = true;
+                    break;
+                  }
+                }
+              }
+              if (anIsIn)
+                aGroupOperations.insert(aFeat);
+            }
+          }
+        }
+      }
+      // insert all new group operations into result and if they are, check for next dependencies
+      aNeedIterate = false;
+      std::set<FeaturePtr>::iterator aGroupOpIter = aGroupOperations.begin();
+      for(; aGroupOpIter != aGroupOperations.end(); aGroupOpIter++) {
+        if (aResSet.find(*aGroupOpIter) == aResSet.end()) {
+          aResSet.insert(*aGroupOpIter);
+          aNeedIterate = true;
+        }
+      }
+    }
+  }
+
+  std::list<FeaturePtr> aResList;
+  std::set<FeaturePtr>::iterator aResIter = aResSet.begin();
+  for(; aResIter != aResSet.end(); aResIter++) {
+    if (theSortResults) { // sort results by creation-order
+      std::list<FeaturePtr>::iterator aListIter = aResList.begin();
+      for(; aListIter != aResList.end(); aListIter++) {
+        if ((*aResIter)->document()->isLater(*aListIter, *aResIter))
+          break;
+      }
+      if (aListIter == aResList.end()) // goes to the end
+        aResList.push_back(*aResIter);
+      else
+        aResList.insert(aListIter, *aResIter);
+    } else //just push to the end unsorted
+      aResList.push_back(*aResIter);
+  }
+  return aResList;
+}
+
+// LCOV_EXCL_STOP
+
 } // namespace ModelAPI_Tools