Salome HOME
Task #3237: Allow usage of accented characters in ObjectBrowser
[modules/shaper.git] / src / ModelAPI / ModelAPI_Tools.cpp
index 54fa5488d558f913289bad9707bbdebe9486d284..e0da11a2f9490ae9ba3e5bb452a64955ff599bd2 100644 (file)
 #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>
 
+// To support old types of GCC (less than 5.0), check the wide-string conversion is working
+#if (__cplusplus >= 201103L || _MSVC_LANG >= 201103L)  && \
+    (__cplusplus >= 201402L || !defined(__GLIBCXX__)   || \
+    (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE > 4))
+#define HAVE_WORKING_WIDESTRING 1
+#else
+#define HAVE_WORKING_WIDESTRING 0
+#endif
+
+#if HAVE_WORKING_WIDESTRING
+#include <codecvt>
+#endif
+
 #include <Events_Loop.h>
 #include <ModelAPI_Events.h>
 
+#include <GeomAPI_ShapeHierarchy.h>
+#include <GeomAPI_ShapeIterator.h>
+
 #define RECURSE_TOP_LEVEL 50
 
 //#define DEBUG_REMOVE_FEATURES
@@ -166,9 +185,10 @@ std::string getFeatureError(const FeaturePtr& theFeature)
 ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGroup,
                        const std::string& theName)
 {
+  std::wstring aName = 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
@@ -332,9 +352,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();
@@ -345,7 +365,7 @@ bool allDocumentsActivated(std::string& theNotActivatedNames)
     if (!aPart->isActivated()) {
       anAllPartActivated = false;
       if (!theNotActivatedNames.empty())
-        theNotActivatedNames += ", ";
+        theNotActivatedNames += L", ";
       theNotActivatedNames += aObject->data()->name().c_str();
     }
   }
@@ -609,7 +629,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;
@@ -621,10 +641,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());
@@ -645,6 +665,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)))
@@ -699,7 +720,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()) {
@@ -707,19 +728,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)
@@ -762,6 +783,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
@@ -787,6 +823,19 @@ void removeResults(const std::list<ResultPtr>& theResults)
 
 // used by GUI only
 // LCOV_EXCL_START
+
+//**************************************************************
+void setDeflection(ResultPtr theResult, const double theDeflection)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeDoublePtr aDeflectionAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID());
+  if (aDeflectionAttr.get() != NULL) {
+    aDeflectionAttr->setValue(theDeflection);
+  }
+}
+
 double getDeflection(const std::shared_ptr<ModelAPI_Result>& theResult)
 {
   double aDeflection = -1;
@@ -803,6 +852,22 @@ double getDeflection(const std::shared_ptr<ModelAPI_Result>& theResult)
   return aDeflection;
 }
 
+//******************************************************
+void setColor(ResultPtr theResult, const std::vector<int>& theColor)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
+  if (aColorAttr.get() != NULL) {
+    if (!aColorAttr->size()) {
+      aColorAttr->setSize(3);
+    }
+    aColorAttr->setValue(0, theColor[0]);
+    aColorAttr->setValue(1, theColor[1]);
+    aColorAttr->setValue(2, theColor[2]);
+  }
+}
 
 void getColor(const std::shared_ptr<ModelAPI_Result>& theResult, std::vector<int>& theColor)
 {
@@ -819,6 +884,88 @@ void getColor(const std::shared_ptr<ModelAPI_Result>& theResult, std::vector<int
   }
 }
 
+//******************************************************
+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
+    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();
+    }
+  }
+}
+
+//******************************************************
+void setIsoLines(ResultPtr theResult, const std::vector<int>& theIso)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeIntArrayPtr aAttr = theResult->data()->intArray(ModelAPI_Result::ISO_LINES_ID());
+  if (aAttr.get() != NULL) {
+    if (!aAttr->size()) {
+      aAttr->setSize(2);
+    }
+    aAttr->setValue(0, theIso[0]);
+    aAttr->setValue(1, theIso[1]);
+  }
+}
+
+//******************************************************
+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)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeDoublePtr anAttribute = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
+  if (anAttribute.get() != NULL) {
+    anAttribute->setValue(theTransparency);
+  }
+}
+
 double getTransparency(const std::shared_ptr<ModelAPI_Result>& theResult)
 {
   double aTransparency = -1;
@@ -832,7 +979,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)
@@ -847,6 +993,16 @@ void copyVisualizationAttrs(
         aDestColor->setValue(a, aSourceColor->value(a));
     }
   }
+  // Iso-lines
+  AttributeIntArrayPtr aSource = theSource->data()->intArray(ModelAPI_Result::ISO_LINES_ID());
+  if (aSource.get() && aSource->isInitialized() && aSource->size()) {
+    AttributeIntArrayPtr aDest = theDest->data()->intArray(ModelAPI_Result::ISO_LINES_ID());
+    if (aDest.get()) {
+      aDest->setSize(aSource->size());
+      for(int a = 0; a < aSource->size(); a++)
+        aDest->setValue(a, aSource->value(a));
+    }
+  }
   // deflection
   AttributeDoublePtr aSourceDefl = theSource->data()->real(ModelAPI_Result::DEFLECTION_ID());
   if (aSourceDefl.get() && aSourceDefl->isInitialized()) {
@@ -894,6 +1050,52 @@ std::list<FeaturePtr> referencedFeatures(
     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>& aRefs = (*aGroupRes)->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() && !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();
@@ -914,4 +1116,42 @@ std::list<FeaturePtr> referencedFeatures(
   return aResList;
 }
 
+// LCOV_EXCL_STOP
+std::string toString(const std::wstring& theWStr)
+{
+#if HAVE_WORKING_WIDESTRING
+  static std::wstring_convert<std::codecvt_utf8<wchar_t> > aConvertor;
+  return aConvertor.to_bytes(theWStr);
+#else
+  char* aBuf = new char[2 * (theWStr.size() + 1)];
+  size_t aNbChars = std::wcstombs(aBuf, theWStr.c_str(), theWStr.size());
+  if (aNbChars != (size_t)-1)
+    aBuf[aNbChars] = '\0';
+  std::string aStr(aBuf);
+  delete[] aBuf;
+  return aStr;
+#endif
+}
+
+/*! Converts a byte string to an extended string
+*  \param theStr a byte string
+*/
+std::wstring toWString(const std::string& theStr)
+{
+#if HAVE_WORKING_WIDESTRING
+  static std::wstring_convert<std::codecvt_utf8<wchar_t> > aConvertor;
+  return aConvertor.from_bytes(theStr);
+#else
+  wchar_t* aBuf = new wchar_t[theStr.size()];
+  size_t aNbWChars = std::mbstowcs(aBuf, theStr.c_str(), theStr.size());
+  if (aNbWChars != (size_t)-1)
+    aBuf[aNbWChars] = '\0';
+  std::wstring aWStr(aBuf);
+  delete[] aBuf;
+  return aWStr;
+#endif
+}
+
+
+
 } // namespace ModelAPI_Tools