Salome HOME
bos #29482 Export of colors and names to STEP.
[modules/shaper.git] / src / ModelHighAPI / ModelHighAPI_Dumper.cpp
index 03047bfa97c8a6e4d9659953b7cf6427f9be2d31..a7a84cefd3de6c7760fb546e721702ce617d9058 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2020  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2022  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
@@ -37,6 +37,8 @@
 #include <GeomDataAPI_Point2D.h>
 #include <GeomDataAPI_Point2DArray.h>
 
+#include <Locale_Convert.h>
+
 #include <ModelAPI_AttributeBoolean.h>
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeDoubleArray.h>
 
 #include <PartSetPlugin_Part.h>
 
-#include <OSD_OpenFile.hxx>
-
 #include <fstream>
+#include <iomanip>
+#include <cctype>
+#include <cmath>
 
 // ===========    Implementation of storage of dumped data    ===========
 static const int THE_DUMP_PRECISION = 16;
@@ -159,7 +162,7 @@ public:
   /// Dump std::endl
   friend
   DumpStorageBuffer& operator<<(DumpStorageBuffer& theBuffer,
-                                std::basic_ostream<char>& (*theEndl)(std::basic_ostream<char>&))
+                                std::basic_ostream<char>& (*)(std::basic_ostream<char>&))
   {
     theBuffer.write("\n");
     return theBuffer;
@@ -258,8 +261,7 @@ void ModelHighAPI_Dumper::DumpStorage::restoreReservedBuffer()
 bool ModelHighAPI_Dumper::DumpStorage::exportTo(const std::string& theFilename,
                                                 const ModulesSet& theUsedModules)
 {
-  std::ofstream aFile;
-  OSD_OpenStream(aFile, theFilename.c_str(), std::ofstream::out);
+  std::ofstream aFile(theFilename.c_str(), std::ofstream::out);
   if (!aFile.is_open())
     return false;
 
@@ -315,7 +317,7 @@ void ModelHighAPI_Dumper::DumpStorage::write(const AttributeSelectionPtr& theAtt
 
   if (aShape.get()) {
     myDumpBuffer << "\"" << aShape->shapeTypeStr() << "\", \""
-                 << theAttrSelect->namingName() << "\"";
+                 << Locale::Convert::toString(theAttrSelect->namingName()) << "\"";
   }
 
   myDumpBuffer << ")";
@@ -496,7 +498,8 @@ void ModelHighAPI_Dumper::DumpStorageWeak::write(const AttributeSelectionPtr& th
     int anIndex = aNExplode.index(aShape);
     if (anIndex != 0) { // found a week-naming index, so, export it
       myDumpBuffer << "model.selection(\"" << aShape->shapeTypeStr() << "\", \""
-                   << theAttrSelect->contextName(aContext) << "\", " << anIndex << ")";
+                   << Locale::Convert::toString(theAttrSelect->contextName(aContext))
+                   << "\", " << anIndex << ")";
       aStandardDump = false;
     }
   }
@@ -569,25 +572,30 @@ static int toInt(const std::string& theString)
 
 const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity,
                                              bool theSaveNotDumped,
-                                             bool theUseEntityName)
-{
-  EntityNameMap::const_iterator aFound = myNames.find(theEntity);
-  if (aFound != myNames.end())
+                                             bool theUseEntityName,
+                                             bool theSetIsDumped)
+{
+  EntityNameMap::iterator aFound = myNames.find(theEntity);
+  if (aFound != myNames.end()) {
+    // Set dumped flag for postponed constraints which are without names
+    if (!aFound->second.myIsDumped)
+      aFound->second.myIsDumped = theSetIsDumped;
     return aFound->second.myCurrentName;
-
+  }
   // entity is not found, store it
-  std::string aName, aKind;
+  std::string aName;
+  std::string aKind;
   bool isDefaultName = false;
   bool isSaveNotDumped = theSaveNotDumped;
   std::ostringstream aDefaultName;
   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theEntity);
   if (aFeature) {
-    aName = aFeature->name();
+    aName = Locale::Convert::toString(aFeature->name());
     aKind = aFeature->getKind();
   } else {
     FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(theEntity);
     if (aFolder) {
-      aName = aFolder->data()->name();
+      aName = Locale::Convert::toString(aFolder->data()->name());
       aKind = ModelAPI_Folder::ID();
       isSaveNotDumped = false;
     }
@@ -633,10 +641,10 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity,
       int aFullIndex = 0;
       NbFeaturesMap::const_iterator aFIt = myFeatureCount.begin();
       for (; aFIt != myFeatureCount.end(); ++aFIt) {
-        std::map<std::string, std::pair<int, int> >::const_iterator aFound =
+        std::map<std::string, std::pair<int, int> >::const_iterator aFoundKind =
           aFIt->second.find(aKind);
-        if (aFound != aFIt->second.end())
-          aFullIndex += aFound->second.first;
+        if (aFoundKind != aFIt->second.end())
+          aFullIndex += aFoundKind->second.first;
       }
       aDefaultName << aKind << "_" << aFullIndex;
     }
@@ -650,6 +658,8 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity,
   if (aFeature)
     saveResultNames(aFeature);
 
+  myNames[theEntity].myIsDumped = theSetIsDumped;
+
   return myNames[theEntity].myCurrentName;
 }
 
@@ -674,13 +684,12 @@ void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature)
   bool isFeatureDefaultName = myNames[theFeature].myIsDefault;
 
   // Save only names of results which is not correspond to default feature name
-  const std::list<ResultPtr>& aResults = theFeature->results();
   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 = (*aRes)->data()->name();
+    std::pair<std::wstring, bool> aName = ModelAPI_Tools::getDefaultName(*aRes, true, true);
+    std::string aDefaultName = Locale::Convert::toString(aName.first);
+    std::string aResName = Locale::Convert::toString((*aRes)->data()->name());
     bool isUserDefined = !(isFeatureDefaultName && aDefaultName == aResName);
     myNames[*aRes] =
       EntityName(aResName, (isUserDefined ? aResName : std::string()), !isUserDefined);
@@ -772,7 +781,7 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeatur
     // dump features in the document
     bool aRes = process(aSubDoc);
     if (isDumpModelDo)
-      *this << "model.do()\n";
+      *this << "\nmodel.do()\n";
     *this << std::endl;
     return aRes;
   }
@@ -864,14 +873,15 @@ void ModelHighAPI_Dumper::dumpSubFeatureNameAndColor(const std::string theSubFea
                                                      const FeaturePtr& theSubFeature)
 {
   name(theSubFeature, false);
-  myNames[theSubFeature] = EntityName(theSubFeatureGet, theSubFeature->name(), false);
+  myNames[theSubFeature] =
+    EntityName(theSubFeatureGet, Locale::Convert::toString(theSubFeature->name()), false);
 
   // store results if they have user-defined names or colors
   std::list<ResultPtr> aResultsWithNameOrColor;
   const std::list<ResultPtr>& aResults = theSubFeature->results();
   std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
   for (; aResIt != aResults.end(); ++aResIt) {
-    std::string aResName = (*aResIt)->data()->name();
+    std::string aResName = Locale::Convert::toString((*aResIt)->data()->name());
     myNames[*aResIt] = EntityName(aResName, aResName, false);
     aResultsWithNameOrColor.push_back(*aResIt);
   }
@@ -982,6 +992,18 @@ bool ModelHighAPI_Dumper::isDumped(const AttributeRefListPtr& theRefList) const
   return true;
 }
 
+size_t ModelHighAPI_Dumper::indexOfFirstNotDumped(
+    const std::shared_ptr<ModelAPI_AttributeRefList>& theRefList) const
+{
+  size_t anIndex = 0;
+  std::list<ObjectPtr> anObjects = theRefList->list();
+  for (std::list<ObjectPtr>::const_iterator anIt = anObjects.begin();
+       anIt != anObjects.end(); ++anIt, ++anIndex)
+    if (!isDumped(ModelAPI_Feature::feature(*anIt)))
+      break;
+  return anIndex;
+}
+
 static bool isSketchSub(const FeaturePtr& theFeature)
 {
   static const std::string SKETCH("Sketch");
@@ -1054,6 +1076,16 @@ bool ModelHighAPI_Dumper::isDefaultTransparency(const ResultPtr& theResult) cons
   return fabs(anAttribute->value()) < 1.e-12;
 }
 
+bool ModelHighAPI_Dumper::dumpCommentBeforeFeature(const FeaturePtr& theFeature) const
+{
+  // currently, the comment should not be dumped only before the filters
+  FiltersFeaturePtr aFilters = std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(theFeature);
+  if (aFilters)
+    return false;
+  // all other features should be commented before the dump
+  return !isDumped(theFeature);
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char theChar)
 {
   *myDumpStorage << theChar;
@@ -1072,6 +1104,12 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::string& theStrin
   return *this;
 }
 
+ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::wstring& theString)
+{
+  *myDumpStorage << Locale::Convert::toString(theString);
+  return *this;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const bool theValue)
 {
   *myDumpStorage << (theValue ? "True" : "False");
@@ -1118,7 +1156,11 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 {
   static const int aSize = 3;
   double aValues[aSize] = {thePoint->x(), thePoint->y(), thePoint->z()};
-  std::string aTexts[aSize] = {thePoint->textX(), thePoint->textY(), thePoint->textZ()};
+  std::string aTexts[aSize] = {
+      Locale::Convert::toString(thePoint->textX()),
+      Locale::Convert::toString(thePoint->textY()),
+      Locale::Convert::toString(thePoint->textZ())
+  };
   myDumpStorage->dumpArray(aSize, aValues, aTexts);
   return *this;
 }
@@ -1128,7 +1170,10 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 {
   static const int aSize = 2;
   double aValues[aSize] = {thePoint->x(), thePoint->y()};
-  std::string aTexts[aSize] = {thePoint->textX(), thePoint->textY()};
+  std::string aTexts[aSize] = {
+      Locale::Convert::toString(thePoint->textX()),
+      Locale::Convert::toString(thePoint->textY())
+  };
   myDumpStorage->dumpArray(aSize, aValues, aTexts);
   return *this;
 }
@@ -1180,7 +1225,7 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeInteger>& theAttrInt)
 {
-  std::string aText = theAttrInt->text();
+  std::string aText = Locale::Convert::toString(theAttrInt->text());
   if (aText.empty())
     *myDumpStorage << theAttrInt->value();
   else
@@ -1205,7 +1250,7 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeDouble>& theAttrReal)
 {
-  std::string aText = theAttrReal->text();
+  std::string aText = Locale::Convert::toString(theAttrReal->text());
   if (aText.empty())
     *myDumpStorage << theAttrReal->value();
   else
@@ -1230,7 +1275,26 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeString>& theAttrStr)
 {
-  *myDumpStorage << "\"" << theAttrStr->value() << "\"";
+  // escaping the quote signs in the string under dumping
+  std::string aStr = theAttrStr->value();
+  /*
+  size_t aPos = aStr.find("\"");
+  while (aPos != std::string::npos) {
+    aStr.insert(aPos, "\\");
+    aPos = aStr.find("\"", aPos + 2);
+  }
+  aPos = aStr.find("\'");
+  while (aPos != std::string::npos) {
+    aStr.insert(aPos, "\\");
+    aPos = aStr.find("\'", aPos + 2);
+  }
+  */
+  size_t aPos = aStr.find_first_of("\"\'");
+  while (aPos != std::string::npos) {
+    aStr.insert(aPos, "\\");
+    aPos = aStr.find_first_of("\"\'", aPos + 2);
+  }
+  *myDumpStorage << "'" << aStr << "'";
   return *this;
 }
 
@@ -1412,6 +1476,11 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     bool isAdded = false;
     std::list<ObjectPtr>::const_iterator anIt = aList.begin();
     for (; anIt != aList.end(); ++anIt) {
+      if (!(*anIt))
+        continue;
+      if (!isDumped(ModelAPI_Feature::feature(*anIt)))
+        break; // stop if the object is not dumped yet (parent feature should be postponed)
+
       if (isAdded)
         *myDumpStorage << ", ";
       else
@@ -1447,10 +1516,10 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeSelectionList>& theAttrSelList)
 {
   static const int aThreshold = 2;
-  static bool aDumpAsIs = false;
+  static int aNbSpaces = 0;
   // if number of elements in the list if greater than a threshold,
   // dump it in a separate line with specific name
-  if (aDumpAsIs || theAttrSelList->size() <= aThreshold) {
+  if (aNbSpaces > 0 || theAttrSelList->size() <= aThreshold) {
     *myDumpStorage << "[";
 
     GeomShapePtr aShape;
@@ -1472,7 +1541,12 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
       }
 
       if(isAdded) {
-        *myDumpStorage << ", ";
+        // print each attribute on separate line with the appropriate shift
+        if (aNbSpaces > 0) {
+          std::string aSpaces(aNbSpaces + 1, ' ');
+          *myDumpStorage << ",\n" << aSpaces;
+        } else
+          *myDumpStorage << ", ";
       } else {
         isAdded = true;
       }
@@ -1506,9 +1580,9 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     }
     // reserve dumped buffer and store list "as is"
     myDumpStorage->reserveBuffer();
-    aDumpAsIs = true;
+    aNbSpaces = (int)aListName.size() + 3;
     *this << aListName << " = " << theAttrSelList << "\n";
-    aDumpAsIs = false;
+    aNbSpaces = 0;
     // append reserved data to the end of the current buffer
     myDumpStorage->restoreReservedBuffer();
     *myDumpStorage << aListName;
@@ -1533,6 +1607,11 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
   return *this;
 }
 
+void ModelHighAPI_Dumper::newline()
+{
+  *this << std::endl;
+}
+
 /// Dump std::endl
 ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
                                 std::basic_ostream<char>& (*theEndl)(std::basic_ostream<char>&))
@@ -1562,6 +1641,7 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
 
   // store all not-dumped entities first
   std::set<EntityPtr> aNotDumped = theDumper.myNotDumpedEntities;
+  theDumper.clearNotDumped();
   theDumper.myDumpStorage->reserveBuffer();
   std::set<EntityPtr>::const_iterator anIt = aNotDumped.begin();
   for (; anIt != aNotDumped.end(); ++anIt) {
@@ -1618,7 +1698,7 @@ void ModelHighAPI_Dumper::exportVariables() const
         exportVariable(anEntry, aNameIter->second.myCurrentName);
         size_t aSize = aFeature->results().size();
         if (aSize > 1) { // additional entries for features with more than one result
-          for(int a = 1; a < aSize; a++) {
+          for(size_t a = 1; a < aSize; a++) {
             std::ostringstream aResEntryStr;
             aResEntryStr<<anEntry<<":"<<a;
             std::string aResEntry = aResEntryStr.str();