Salome HOME
Copyrights update 2013
[modules/smesh.git] / src / SMESH_I / SMESH_DumpPython.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File    : SMESH_DumpPython.cxx
23 //  Created : Thu Mar 24 17:17:59 2005
24 //  Author  : Julia DOROVSKIKH
25 //  Module  : SMESH
26
27 #include "SMESH_PythonDump.hxx"
28
29 #include "SMESH_2smeshpy.hxx"
30 #include "SMESH_Comment.hxx"
31 #include "SMESH_Filter_i.hxx"
32 #include "SMESH_Gen_i.hxx"
33 #include "SMESH_MeshEditor_i.hxx"
34
35 #include <SALOMEDS_wrap.hxx>
36
37 #include <TColStd_HSequenceOfInteger.hxx>
38 #include <TCollection_AsciiString.hxx>
39
40 #ifdef _DEBUG_
41 static int MYDEBUG = 0;
42 #else
43 static int MYDEBUG = 0;
44 #endif
45
46 namespace SMESH
47 {
48
49   size_t TPythonDump::myCounter = 0;
50   const char theNotPublishedObjectName[] = "__NOT__Published__Object__";
51
52   TVar::TVar(CORBA::Double value):myVals(1) { myVals[0] = SMESH_Comment(value); }
53   TVar::TVar(CORBA::Long   value):myVals(1) { myVals[0] = SMESH_Comment(value); }
54   TVar::TVar(CORBA::Short  value):myVals(1) { myVals[0] = SMESH_Comment(value); }
55   TVar::TVar(const SMESH::double_array& value):myVals(value.length())
56   {
57     for ( size_t i = 0; i < value.length(); i++)
58       myVals[i] = SMESH_Comment(value[i]);
59   }
60
61   TPythonDump::
62   TPythonDump():myVarsCounter(0)
63   {
64     ++myCounter;
65   }
66   TPythonDump::
67   ~TPythonDump()
68   {
69     if(--myCounter == 0){
70       SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
71       std::string aString = myStream.str();
72       TCollection_AsciiString aCollection(Standard_CString(aString.c_str()));
73       SALOMEDS::Study_var aStudy = aSMESHGen->GetCurrentStudy();
74       if(!aStudy->_is_nil() && !aCollection.IsEmpty())
75       {
76         aSMESHGen->AddToPythonScript(aStudy->StudyId(),aCollection);
77         if(MYDEBUG) MESSAGE(aString);
78         // prevent misuse of already treated variables
79         aSMESHGen->UpdateParameters(CORBA::Object_var().in(),"");
80       }
81     }
82   }
83
84   TPythonDump& //!< store a variable value. Write either a value or '$varID$'
85   TPythonDump::
86   operator<<(const TVar& theVarValue)
87   {
88     const std::vector< int >& varIDs = SMESH_Gen_i::GetSMESHGen()->GetLastParamIndices();
89     if ( theVarValue.myVals.size() != 1 )
90     {
91       myStream << "[ ";
92       for ( size_t i = 1; i <= theVarValue.myVals.size(); ++i )
93       {
94         if ( myVarsCounter < varIDs.size() && varIDs[ myVarsCounter ] >= 0 )
95           myStream << TVar::Quote() << varIDs[ myVarsCounter ] << TVar::Quote();
96         else
97           myStream << theVarValue.myVals[i-1];
98         if ( i < theVarValue.myVals.size() )
99           myStream << ", ";
100         ++myVarsCounter;
101       }
102       myStream << " ]";
103     }
104     else
105     {
106       if ( myVarsCounter < varIDs.size() && varIDs[ myVarsCounter ] >= 0 )
107         myStream << TVar::Quote() << varIDs[ myVarsCounter ] << TVar::Quote();
108       else
109         myStream << theVarValue.myVals[0];
110       ++myVarsCounter;
111     }
112     return *this;
113   }
114
115   TPythonDump&
116   TPythonDump::
117   operator<<(long int theArg){
118     myStream<<theArg;
119     return *this;
120   }
121
122   TPythonDump&
123   TPythonDump::
124   operator<<(int theArg){
125     myStream<<theArg;
126     return *this;
127   }
128
129   TPythonDump&
130   TPythonDump::
131   operator<<(double theArg){
132     myStream<<theArg;
133     return *this;
134   }
135
136   TPythonDump&
137   TPythonDump::
138   operator<<(float theArg){
139     myStream<<theArg;
140     return *this;
141   }
142
143   TPythonDump&
144   TPythonDump::
145   operator<<(const void* theArg){
146     myStream<<theArg;
147     return *this;
148   }
149
150   TPythonDump&
151   TPythonDump::
152   operator<<(const char* theArg){
153     if ( theArg )
154       myStream<<theArg;
155     return *this;
156   }
157
158   TPythonDump&
159   TPythonDump::
160   operator<<(const SMESH::ElementType& theArg)
161   {
162     myStream<<"SMESH.";
163     switch(theArg){
164     case ALL:    myStream<<"ALL";    break;
165     case NODE:   myStream<<"NODE";   break;
166     case EDGE:   myStream<<"EDGE";   break;
167     case FACE:   myStream<<"FACE";   break;
168     case VOLUME: myStream<<"VOLUME"; break;
169     case ELEM0D: myStream<<"ELEM0D"; break;
170     case BALL:   myStream<<"BALL";   break;
171     default:     myStream<<"__UNKNOWN__ElementType: " << theArg;
172     }
173     return *this;
174   }
175
176   TPythonDump&
177   TPythonDump::
178   operator<<(const SMESH::GeometryType& theArg)
179   {
180     myStream<<"SMESH.";
181     switch(theArg){
182     case Geom_POINT:      myStream<<"Geom_POINT";      break;
183     case Geom_EDGE:       myStream<<"Geom_EDGE";       break;
184     case Geom_TRIANGLE:   myStream<<"Geom_TRIANGLE";   break;
185     case Geom_QUADRANGLE: myStream<<"Geom_QUADRANGLE"; break;
186     case Geom_POLYGON:    myStream<<"Geom_POLYGON";    break;
187     case Geom_TETRA:      myStream<<"Geom_TETRA";      break;
188     case Geom_PYRAMID:    myStream<<"Geom_PYRAMID";    break;
189     case Geom_HEXA:       myStream<<"Geom_HEXA";       break;
190     case Geom_PENTA:      myStream<<"Geom_PENTA";      break;
191     case Geom_POLYHEDRA:  myStream<<"Geom_POLYHEDRA";  break;
192     case Geom_BALL:       myStream<<"Geom_BALL";       break;
193     default:    myStream<<"__UNKNOWN__GeometryType: " << theArg;
194     }
195     return *this;
196   }
197   TPythonDump&
198   TPythonDump::
199   operator<<(const SMESH::EntityType& theArg)
200   {
201     myStream<<"SMESH.";
202     switch(theArg){
203     case Entity_0D:                myStream<<"Entity_0D";                break;
204     case Entity_Edge:              myStream<<"Entity_Edge";              break;
205     case Entity_Quad_Edge:         myStream<<"Entity_Quad_Edge";         break;
206     case Entity_Triangle:          myStream<<"Entity_Triangle";          break;
207     case Entity_Quad_Triangle:     myStream<<"Entity_Quad_Triangle";     break;
208     case Entity_Quadrangle:        myStream<<"Entity_Quadrangle";        break;
209     case Entity_Quad_Quadrangle:   myStream<<"Entity_Quad_Quadrangle";   break;
210     case Entity_BiQuad_Quadrangle: myStream<<"Entity_BiQuad_Quadrangle"; break;
211     case Entity_Polygon:           myStream<<"Entity_Polygon";           break;
212     case Entity_Quad_Polygon:      myStream<<"Entity_Quad_Polygon";      break;
213     case Entity_Tetra:             myStream<<"Entity_Tetra";             break;
214     case Entity_Quad_Tetra:        myStream<<"Entity_Quad_Tetra";        break;
215     case Entity_Pyramid:           myStream<<"Entity_Pyramid";           break;
216     case Entity_Quad_Pyramid:      myStream<<"Entity_Quad_Pyramid";      break;
217     case Entity_Hexa:              myStream<<"Entity_Hexa";              break;
218     case Entity_Quad_Hexa:         myStream<<"Entity_Quad_Hexa";         break;
219     case Entity_TriQuad_Hexa:      myStream<<"Entity_TriQuad_Hexa";      break;
220     case Entity_Penta:             myStream<<"Entity_Penta";             break;
221     case Entity_Quad_Penta:        myStream<<"Entity_Quad_Penta";        break;
222     case Entity_Hexagonal_Prism:   myStream<<"Entity_Hexagonal_Prism";   break;
223     case Entity_Polyhedra:         myStream<<"Entity_Polyhedra";         break;
224     case Entity_Quad_Polyhedra:    myStream<<"Entity_Quad_Polyhedra";    break;
225     case Entity_Ball:              myStream<<"Entity_Ball";              break;
226     case Entity_Last:              myStream<<"Entity_Last";              break;
227     default:    myStream<<"__UNKNOWN__EntityType: " << theArg;
228     }
229     return *this;
230   }
231
232   template<class TArray>
233   void DumpArray(const TArray& theArray, TPythonDump & theStream)
234   {
235     theStream << "[ ";
236     for (int i = 1; i <= theArray.length(); i++) {
237       theStream << theArray[i-1];
238       if ( i < theArray.length() )
239         theStream << ", ";
240     }
241     theStream << " ]";
242   }
243
244   TPythonDump&
245   TPythonDump::operator<<(const SMESH::long_array& theArg)
246   {
247     DumpArray( theArg, *this );
248     return *this;
249   }
250
251   TPythonDump&
252   TPythonDump::operator<<(const SMESH::double_array& theArg)
253   {
254     DumpArray( theArg, *this );
255     return *this;
256   }
257
258   TPythonDump&
259   TPythonDump::operator<<(const SMESH::string_array& theArray)
260   {
261     myStream << "[ ";
262     for (int i = 1; i <= theArray.length(); i++) {
263       myStream << "'" << theArray[i-1] << "'";
264       if ( i < theArray.length() )
265         myStream << ", ";
266     }
267     myStream << " ]";
268     return *this;
269   }
270
271   TPythonDump&
272   TPythonDump::
273   operator<<(SALOMEDS::SObject_ptr aSObject)
274   {
275     if ( !aSObject->_is_nil() ) {
276       CORBA::String_var entry = aSObject->GetID();
277       myStream << entry.in();
278     }
279     else {
280       myStream << theNotPublishedObjectName;
281     }
282     return *this;
283   }
284
285   TPythonDump&
286   TPythonDump::
287   operator<<(CORBA::Object_ptr theArg)
288   {
289     SMESH_Gen_i*          aSMESHGen = SMESH_Gen_i::GetSMESHGen();
290     SALOMEDS::Study_var      aStudy = aSMESHGen->GetCurrentStudy();
291     SALOMEDS::SObject_wrap aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
292     if(!aSObject->_is_nil()) {
293       CORBA::String_var id = aSObject->GetID();
294       myStream << id;
295     } else if ( !CORBA::is_nil(theArg)) {
296       if ( aSMESHGen->CanPublishInStudy( theArg )) // not published SMESH object
297         myStream << "smeshObj_" << size_t(theArg);
298       else
299         myStream << theNotPublishedObjectName;
300     }
301     else
302       myStream << "None";
303     return *this;
304   }
305
306   TPythonDump&
307   TPythonDump::
308   operator<<(SMESH::SMESH_Hypothesis_ptr theArg)
309   {
310     SALOMEDS::Study_var     aStudy = SMESH_Gen_i::GetSMESHGen()->GetCurrentStudy();
311     SALOMEDS::SObject_wrap aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
312     if(aSObject->_is_nil() && !CORBA::is_nil(theArg))
313       myStream << "hyp_" << theArg->GetId();
314     else
315       *this << CORBA::Object_ptr( theArg );
316     return *this;
317   }
318
319   TPythonDump&
320   TPythonDump::
321   operator<<(SMESH::SMESH_IDSource_ptr theArg)
322   {
323     if ( CORBA::is_nil( theArg ) )
324       return *this << "None";
325     SMESH_Gen_i*          aSMESHGen = SMESH_Gen_i::GetSMESHGen();
326     SALOMEDS::Study_var      aStudy = aSMESHGen->GetCurrentStudy();
327     SALOMEDS::SObject_wrap aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
328     if(!aSObject->_is_nil())
329     {
330       return *this << aSObject;
331     }
332     if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theArg ))
333     {
334       return *this << filter;
335     }
336     if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theArg ))
337     {
338       SMESH::SMESH_Mesh_var            mesh = theArg->GetMesh();
339       SMESH::long_array_var    anElementsId = theArg->GetIDs();
340       SMESH::array_of_ElementType_var types = theArg->GetTypes();
341       SMESH::ElementType type = types->length() ? types[0] : SMESH::ALL;
342       return *this << mesh << ".GetIDSource(" << anElementsId << ", " << type << ")";
343     }
344     return *this << theNotPublishedObjectName;
345   }
346
347   TPythonDump&
348   TPythonDump::
349   operator<<(SMESH::FilterLibrary_i* theArg)
350   {
351     myStream<<"aFilterLibrary"<<theArg;
352     return *this;
353   }
354
355   TPythonDump&
356   TPythonDump::
357   operator<<(SMESH::FilterManager_i* theArg)
358   {
359     myStream<<"aFilterManager";
360     return *this;
361   }
362
363   TPythonDump&
364   TPythonDump::
365   operator<<(SMESH::Filter_i* theArg)
366   {
367     myStream<<"aFilter"<<theArg;
368     return *this;
369   }
370
371   TPythonDump&
372   TPythonDump::
373   operator<<(SMESH::Functor_i* theArg)
374   {
375     if ( theArg ) {
376       FunctorType aFunctorType = theArg->GetFunctorType();
377       switch(aFunctorType){
378       case FT_AspectRatio:           myStream<< "anAspectRatio";          break;
379       case FT_AspectRatio3D:         myStream<< "anAspectRatio3D";        break;
380       case FT_Warping:               myStream<< "aWarping";               break;
381       case FT_MinimumAngle:          myStream<< "aMinimumAngle";          break;
382       case FT_Taper:                 myStream<< "aTaper";                 break;
383       case FT_Skew:                  myStream<< "aSkew";                  break;
384       case FT_Area:                  myStream<< "aArea";                  break;
385       case FT_Volume3D:              myStream<< "aVolume3D";              break;
386       case FT_MaxElementLength2D:    myStream<< "aMaxElementLength2D";    break;
387       case FT_MaxElementLength3D:    myStream<< "aMaxElementLength3D";    break;
388       case FT_FreeBorders:           myStream<< "aFreeBorders";           break;
389       case FT_FreeEdges:             myStream<< "aFreeEdges";             break;
390       case FT_FreeNodes:             myStream<< "aFreeNodes";             break;
391       case FT_FreeFaces:             myStream<< "aFreeFaces";             break;
392       case FT_MultiConnection:       myStream<< "aMultiConnection";       break;
393       case FT_MultiConnection2D:     myStream<< "aMultiConnection2D";     break;
394       case FT_Length:                myStream<< "aLength";                break;
395       case FT_Length2D:              myStream<< "aLength2D";              break;
396       case FT_BelongToGeom:          myStream<< "aBelongToGeom";          break;
397       case FT_BelongToPlane:         myStream<< "aBelongToPlane";         break;
398       case FT_BelongToCylinder:      myStream<< "aBelongToCylinder";      break;
399       case FT_BelongToGenSurface:    myStream<< "aBelongToGenSurface";    break;
400       case FT_LyingOnGeom:           myStream<< "aLyingOnGeom";           break;
401       case FT_CoplanarFaces:         myStream<< "aCoplanarFaces";         break;
402       case FT_RangeOfIds:            myStream<< "aRangeOfIds";            break;
403       case FT_BadOrientedVolume:     myStream<< "aBadOrientedVolume";     break;
404       case FT_BareBorderVolume:      myStream<< "aBareBorderVolume";      break;
405       case FT_BareBorderFace:        myStream<< "aBareBorderFace";        break;
406       case FT_OverConstrainedVolume: myStream<< "aOverConstrainedVolume"; break;
407       case FT_OverConstrainedFace:   myStream<< "aOverConstrainedFace";   break;
408       case FT_LinearOrQuadratic:     myStream<< "aLinearOrQuadratic";     break;
409       case FT_GroupColor:            myStream<< "aGroupColor";            break;
410       case FT_ElemGeomType:          myStream<< "anElemGeomType";         break;
411       case FT_LessThan:              myStream<< "aLessThan";              break;
412       case FT_MoreThan:              myStream<< "aMoreThan";              break;
413       case FT_EqualTo:               myStream<< "anEqualTo";              break;
414       case FT_LogicalNOT:            myStream<< "aLogicalNOT";            break;
415       case FT_LogicalAND:            myStream<< "aLogicalAND";            break;
416       case FT_LogicalOR:             myStream<< "aLogicalOR";             break;
417       case FT_Undefined:
418       default:                       myStream<< "anUndefined";            break;
419       }
420       myStream<<theArg;
421     }
422     return *this;
423   }
424
425   TPythonDump&
426   TPythonDump::
427   operator<<(SMESH::Measurements_i* theArg)
428   {
429     myStream<<"aMeasurements";
430     return *this;
431   }
432
433
434   TPythonDump& TPythonDump:: operator<<(SMESH_Gen_i* theArg)
435   {
436     myStream << SMESHGenName(); return *this;
437   }
438
439   TPythonDump& TPythonDump::operator<<(SMESH_MeshEditor_i* theArg)
440   {
441     myStream << MeshEditorName() << "_" << ( theArg ? theArg->GetMeshId() : -1 ); return *this;
442   }
443
444   TPythonDump& TPythonDump::operator<<(const TCollection_AsciiString & theStr)
445   {
446     myStream << theStr; return *this;
447   }
448
449
450   TPythonDump& TPythonDump::operator<<(SMESH::MED_VERSION theVersion)
451   {
452     switch (theVersion) {
453     case SMESH::MED_V2_1: myStream << "SMESH.MED_V2_1"; break;
454     case SMESH::MED_V2_2: myStream << "SMESH.MED_V2_2"; break;
455     default: myStream << theVersion;
456     }
457     return *this;
458   }
459
460   TPythonDump& TPythonDump::operator<<(const SMESH::AxisStruct & theAxis)
461   {
462     *this << "SMESH.AxisStruct( "
463           << TVar( theAxis.x  ) << ", "
464           << TVar( theAxis.y  ) << ", "
465           << TVar( theAxis.z  ) << ", "
466           << TVar( theAxis.vx ) << ", "
467           << TVar( theAxis.vy ) << ", "
468           << TVar( theAxis.vz ) << " )";
469     return *this;
470   }
471
472   TPythonDump& TPythonDump::operator<<(const SMESH::DirStruct & theDir)
473   {
474     const SMESH::PointStruct & P = theDir.PS;
475     *this << "SMESH.DirStruct( SMESH.PointStruct ( "
476           << TVar( P.x ) << ", "
477           << TVar( P.y ) << ", "
478           << TVar( P.z ) << " ))";
479     return *this;
480   }
481
482   TPythonDump& TPythonDump::operator<<(const SMESH::PointStruct & P)
483   {
484     *this << "SMESH.PointStruct ( "
485           << TVar( P.x ) << ", "
486           << TVar( P.y ) << ", "
487           << TVar( P.z ) << " )";
488     return *this;
489   }
490
491   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfGroups& theList)
492   {
493     DumpArray( theList, *this );
494     return *this;
495   }
496   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfGroups * theList)
497   {
498     DumpArray( *theList, *this );
499     return *this;
500   }
501   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfIDSources& theList)
502   {
503     DumpArray( theList, *this );
504     return *this;
505   }
506   const char* TPythonDump::NotPublishedObjectName()
507   {
508     return theNotPublishedObjectName;
509   }
510
511   TCollection_AsciiString myLongStringStart( "TPythonDump::LongStringStart" );
512   TCollection_AsciiString myLongStringEnd  ( "TPythonDump::LongStringEnd" );
513
514   //================================================================================
515   /*!
516    * \brief Return marker of long string literal beginning
517    * \param type - a name of functionality producing the string literal
518    * \retval TCollection_AsciiString - the marker string to be written into
519    * a raw python script
520    */
521   //================================================================================
522
523   TCollection_AsciiString TPythonDump::LongStringStart(const char* type)
524   {
525     return
526       myLongStringStart +
527       (Standard_Integer) strlen(type) +
528       " " +
529       (char*) type;
530   }
531
532   //================================================================================
533   /*!
534      * \brief Return marker of long string literal end
535       * \retval TCollection_AsciiString - the marker string to be written into
536       * a raw python script
537    */
538   //================================================================================
539
540   TCollection_AsciiString TPythonDump::LongStringEnd()
541   {
542     return myLongStringEnd;
543   }
544
545   //================================================================================
546   /*!
547      * \brief Cut out a long string literal from a string
548       * \param theText - text possibly containing string literals
549       * \param theFrom - position in the text to search from
550       * \param theLongString - the retrieved literal
551       * \param theStringType - a name of functionality produced the literal
552       * \retval bool - true if a string literal found
553      *
554      * The literal is removed from theText; theFrom points position right after
555      * the removed literal
556    */
557   //================================================================================
558
559   bool  TPythonDump::CutoutLongString( TCollection_AsciiString & theText,
560                                        int                     & theFrom,
561                                        TCollection_AsciiString & theLongString,
562                                        TCollection_AsciiString & theStringType)
563   {
564     if ( theFrom < 1 || theFrom > theText.Length() )
565       return false;
566
567     // ...script \  beg marker    \ \ type \       literal              \  end marker  \ script...
568     //  "theText myLongStringStart7 Pattern!!! SALOME Mesh Pattern file myLongStringEndtextEnd"
569     //  012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
570     //  0         1         2         3         4         5         6         7         8
571
572     theFrom = theText.Location( myLongStringStart, theFrom, theText.Length() ); // = 09
573     if ( !theFrom )
574       return false;
575
576     // find where literal begins
577     int literalBeg = theFrom + myLongStringStart.Length(); // = 26
578     char* typeLenStr = (char*) theText.ToCString() + literalBeg - 1; // = "7 Pattern!!! SALO...."
579     int typeLen = atoi ( typeLenStr ); // = 7
580     while ( *typeLenStr != ' ' ) { // look for ' ' after typeLen
581       literalBeg++; // 26 -> 27
582       typeLenStr++;
583     }
584     literalBeg += typeLen + 1; // = 35
585     if ( literalBeg > theText.Length() )
586       return false;
587
588     // where literal ends (i.e. end marker begins)
589     int literalEnd = theText.Location( myLongStringEnd, literalBeg, theText.Length() ); // = 64
590     if ( !literalEnd )
591       literalEnd = theText.Length();
592
593     // literal
594     theLongString = theText.SubString( literalBeg, literalEnd - 1); // "!!! SALOME Mesh Pattern file "
595     // type
596     theStringType = theText.SubString( literalBeg - typeLen, literalBeg - 1 ); // "Pattern"
597     // cut off literal
598     literalEnd += myLongStringEnd.Length(); // = 79
599     TCollection_AsciiString textEnd = theText.SubString( literalEnd, theText.Length() ); // "textE..."
600     theText = theText.SubString( 1, theFrom - 1 ) + textEnd;
601
602     return true;
603   }
604 }
605
606 //=======================================================================
607 //function : RemoveTabulation
608 //purpose  : 
609 //=======================================================================
610 void RemoveTabulation( TCollection_AsciiString& theScript )
611 {
612   std::string aString( theScript.ToCString() );
613   std::string::size_type aPos = 0;
614   while( aPos < aString.length() )
615   {
616     aPos = aString.find( "\n\t", aPos );
617     if( aPos == std::string::npos )
618       break;
619     aString.replace( aPos, 2, "\n" );
620     aPos++;
621   }
622   theScript = aString.c_str();
623 }
624
625 //=======================================================================
626 //function : DumpPython
627 //purpose  :
628 //=======================================================================
629 Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Object_ptr theStudy,
630                                            CORBA::Boolean isPublished,
631                                            CORBA::Boolean isMultiFile,
632                                            CORBA::Boolean& isValidScript)
633 {
634   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
635   if (CORBA::is_nil(aStudy))
636     return new Engines::TMPFile(0);
637
638   CORBA::String_var compDataType = ComponentDataType();
639   SALOMEDS::SObject_wrap aSO = aStudy->FindComponent( compDataType.in() );
640   if (CORBA::is_nil(aSO))
641     return new Engines::TMPFile(0);
642
643   // Map study entries to object names
644   Resource_DataMapOfAsciiStringAsciiString aMap;
645   Resource_DataMapOfAsciiStringAsciiString aMapNames;
646   //TCollection_AsciiString s ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
647
648   SALOMEDS::ChildIterator_wrap Itr = aStudy->NewChildIterator(aSO);
649   for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
650     SALOMEDS::SObject_wrap aValue = Itr->Value();
651     CORBA::String_var anID = aValue->GetID();
652     CORBA::String_var aName = aValue->GetName();
653     TCollection_AsciiString aGUIName ( (char*) aName.in() );
654     TCollection_AsciiString anEnrty ( (char*) anID.in() );
655     if (aGUIName.Length() > 0) {
656       aMapNames.Bind( anEnrty, aGUIName );
657       aMap.Bind( anEnrty, aGUIName );
658     }
659   }
660
661   // Get trace of restored study
662   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
663   SALOMEDS::GenericAttribute_wrap anAttr =
664     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
665
666   SALOMEDS::AttributePythonObject_var pyAttr =
667     SALOMEDS::AttributePythonObject::_narrow(anAttr);
668   CORBA::String_var oldValue = pyAttr->GetObject();
669   TCollection_AsciiString aSavedTrace (oldValue.in());
670
671   // Add trace of API methods calls and replace study entries by names
672   TCollection_AsciiString aScript;
673   aScript += DumpPython_impl(aStudy, aMap, aMapNames, isPublished, isMultiFile,
674                              myIsHistoricalPythonDump, isValidScript, aSavedTrace);
675
676   int aLen = aScript.Length();
677   unsigned char* aBuffer = new unsigned char[aLen+1];
678   strcpy((char*)aBuffer, aScript.ToCString());
679
680   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
681   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aLen+1, aLen+1, anOctetBuf, 1);
682
683   bool hasNotPublishedObjects = aScript.Location( SMESH::theNotPublishedObjectName, 1, aLen);
684   isValidScript = isValidScript && !hasNotPublishedObjects;
685
686   return aStreamFile._retn();
687 }
688
689 //=============================================================================
690 /*!
691  *  AddToPythonScript
692  */
693 //=============================================================================
694 void SMESH_Gen_i::AddToPythonScript (int theStudyID, const TCollection_AsciiString& theString)
695 {
696   if (myPythonScripts.find(theStudyID) == myPythonScripts.end()) {
697     myPythonScripts[theStudyID] = new TColStd_HSequenceOfAsciiString;
698   }
699   myPythonScripts[theStudyID]->Append(theString);
700 }
701
702 //=============================================================================
703 /*!
704  *  RemoveLastFromPythonScript
705  */
706 //=============================================================================
707 void SMESH_Gen_i::RemoveLastFromPythonScript (int theStudyID)
708 {
709   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
710     int aLen = myPythonScripts[theStudyID]->Length();
711     myPythonScripts[theStudyID]->Remove(aLen);
712   }
713 }
714
715 //=======================================================================
716 //function : SavePython
717 //purpose  :
718 //=======================================================================
719 void SMESH_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
720 {
721   // Dump trace of API methods calls
722   TCollection_AsciiString aScript = GetNewPythonLines(theStudy->StudyId());
723
724   // Check contents of PythonObject attribute
725   CORBA::String_var compDataType = ComponentDataType();
726   SALOMEDS::SObject_wrap aSO = theStudy->FindComponent( compDataType.in() );
727   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
728   SALOMEDS::GenericAttribute_wrap anAttr =
729     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
730
731   SALOMEDS::AttributePythonObject_var pyAttr =
732     SALOMEDS::AttributePythonObject::_narrow(anAttr);
733   CORBA::String_var oldValue = pyAttr->GetObject();
734   TCollection_AsciiString oldScript (oldValue.in());
735
736   if (oldScript.Length() > 0) {
737     oldScript += "\n";
738     oldScript += aScript;
739   } else {
740     oldScript = aScript;
741   }
742
743   // Store in PythonObject attribute
744   pyAttr->SetObject(oldScript.ToCString(), 1);
745
746   // Clean trace of API methods calls
747   CleanPythonTrace(theStudy->StudyId());
748 }
749
750
751 // impl
752
753
754 //=============================================================================
755 /*!
756  *  FindEntries: Returns a sequence of start/end positions of entries in the string
757  */
758 //=============================================================================
759 Handle(TColStd_HSequenceOfInteger) FindEntries (TCollection_AsciiString& theString)
760 {
761   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
762   Standard_Integer aLen = theString.Length();
763   Standard_Boolean isFound = Standard_False;
764
765   char* arr = (char*) theString.ToCString();
766   Standard_Integer i = 0, j;
767
768   while(i < aLen) {
769     int c = (int)arr[i];
770     j = i+1;
771     if ( isdigit( c )) { //Is digit?
772
773       isFound = Standard_False;
774       while((j < aLen) && ( isdigit(c) || c == ':' )) { //Check if it is an entry
775         c = (int)arr[j++];
776         if(c == ':') isFound = Standard_True;
777       }
778
779       if (isFound) {
780         int prev = (i < 1) ? 0 : (int)arr[i - 1];
781         // to distinguish from a sketcher command:
782         // last char should be a digit, not ":",
783         // previous char should not be '"'.
784         if (arr[j-2] != ':' && prev != '"') {
785           aSeq->Append(i+1); // +1 because AsciiString starts from 1
786           aSeq->Append(j-1);
787         }
788       }
789     }
790
791     i = j;
792   }
793
794   return aSeq;
795 }
796
797 namespace {
798
799   //================================================================================
800   /*!
801    * \brief Make a string be a valid python name
802     * \param aName - a string to fix
803     * \retval bool - true if aName was not modified
804    */
805   //================================================================================
806
807   bool fixPythonName(TCollection_AsciiString & aName )
808   {
809     const TCollection_AsciiString allowedChars =
810       "qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_";
811     bool isValidName = true;
812     int nbUnderscore = 0;
813     int p=1; // replace not allowed chars by underscore
814     while (p <= aName.Length() &&
815            (p = aName.FirstLocationNotInSet(allowedChars, p, aName.Length())))
816     {
817       if ( p == 1 || p == aName.Length() || aName.Value(p-1) == '_')
818         aName.Remove( p, 1 ); // remove double _ from the start and the end
819       else
820         aName.SetValue(p, '_'), nbUnderscore++;
821       isValidName = false;
822     }
823     if ( aName.IsIntegerValue() ) { // aName must not start with a digit
824       aName.Insert( 1, 'a' );
825       isValidName = false;
826     }
827     // shorten names like CartesianParameters3D_400_400_400_1000000_1
828     const int nbAllowedUnderscore = 3; /* changed from 2 to 3 by an user request
829                                           posted to SALOME Forum */
830     if ( aName.Length() > 20 && nbUnderscore > nbAllowedUnderscore )
831     {
832       p = aName.Location( "_", 20, aName.Length());
833       if ( p > 1 )
834         aName.Trunc( p-1 );
835     }
836     return isValidName;
837   }
838 }
839
840 //=============================================================================
841 /*!
842  *  DumpPython
843  */
844 //=============================================================================
845 TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
846                         (SALOMEDS::Study_ptr                       theStudy,
847                          Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
848                          Resource_DataMapOfAsciiStringAsciiString& theNames,
849                          bool                                      isPublished,
850                          bool                                      isMultiFile,
851                          bool                                      isHistoricalDump,
852                          bool&                                     aValidScript,
853                          const TCollection_AsciiString&            theSavedTrace)
854 {
855   int aStudyID = theStudy->StudyId();
856
857   TCollection_AsciiString helper; // to comfortably concatenate C strings
858   TCollection_AsciiString aSmeshpy( SMESH_2smeshpy::SmeshpyName() );
859   TCollection_AsciiString aSMESHGen( SMESH_2smeshpy::GenName() );
860   TCollection_AsciiString anOldGen( SMESH::TPythonDump::SMESHGenName() );
861
862   TCollection_AsciiString aScript;
863   if( isMultiFile )
864     aScript += "def RebuildData(theStudy):";
865   aScript += "\n\t";
866   aScript += helper + "aFilterManager = " + aSMESHGen + ".CreateFilterManager()\n\t";
867   aScript += helper + "aMeasurements = " + aSMESHGen + ".CreateMeasurements()\n\t";
868   if ( isPublished )
869     aScript += aSMESHGen + ".SetCurrentStudy(theStudy)";
870   else
871     aScript += aSMESHGen + ".SetCurrentStudy(None)";
872
873   // import python files corresponding to plugins
874   set<string> moduleNameSet;
875   map<string, GenericHypothesisCreator_i*>::iterator hyp_creator = myHypCreatorMap.begin();
876   for ( ; hyp_creator != myHypCreatorMap.end(); ++hyp_creator ) {
877     string moduleName = hyp_creator->second->GetModuleName();
878     bool newModule = moduleNameSet.insert( moduleName ).second;
879     if ( newModule )
880       aScript += helper + "\n\t" + "import " + (char*) moduleName.c_str();
881   }
882
883   // Dump trace of restored study
884   if (theSavedTrace.Length() > 0) {
885     // For the convertion of IDL API calls -> smesh.py API, "smesh" standing for SMESH_Gen
886     // was replaces with "smeshgen" (==TPythonDump::SMESHGenName()).
887     // Change "smesh" -> "smeshgen" in the trace saved before passage to smesh.py API
888     bool isNewVersion =
889       theSavedTrace.Location( anOldGen + ".", 1, theSavedTrace.Length() );
890     if ( !isNewVersion ) {
891       TCollection_AsciiString aSavedTrace( theSavedTrace );
892       TCollection_AsciiString aSmeshCall ( "smesh." ), gen( "gen" );
893       int beg, end = aSavedTrace.Length(), from = 1;
894       while ( from < end && ( beg = aSavedTrace.Location( aSmeshCall, from, end ))) {
895         char charBefore = ( beg == 1 ) ? ' ' : aSavedTrace.Value( beg - 1 );
896         if ( isspace( charBefore ) || charBefore == '=' ) { // "smesh." is not a part of a long word
897           aSavedTrace.Insert( beg + aSmeshCall.Length() - 1, gen );// "smesh" -> "smeshgen"
898           end += gen.Length();
899         }
900         from = beg + aSmeshCall.Length();
901       }
902       aScript += helper + "\n" + aSavedTrace;
903     }
904     else
905       // append a saved trace to the script
906       aScript += helper + "\n" + theSavedTrace;
907   }
908
909   // Dump trace of API methods calls
910   TCollection_AsciiString aNewLines = GetNewPythonLines(aStudyID);
911   if (aNewLines.Length() > 0) {
912     aScript += helper + "\n" + aNewLines;
913   }
914
915   // Convert IDL API calls into smesh.py API.
916   // Some objects are wrapped with python classes and
917   // Resource_DataMapOfAsciiStringAsciiString holds methods returning wrapped objects
918   Resource_DataMapOfAsciiStringAsciiString anEntry2AccessorMethod;
919   std::set< TCollection_AsciiString >      aRemovedObjIDs;
920   if ( !getenv("NO_2smeshpy_conversion"))
921     aScript = SMESH_2smeshpy::ConvertScript( aScript, anEntry2AccessorMethod,
922                                              theObjectNames, aRemovedObjIDs,
923                                              theStudy, isHistoricalDump );
924
925   // Replace characters used instead of quote marks to quote notebook variables
926   {
927     int pos = 1;
928     while (( pos = aScript.Location( 1, SMESH::TVar::Quote(), pos, aScript.Length() )))
929       aScript.SetValue( pos, '"' );
930   }
931
932   // Find entries to be replaced by names
933   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
934   Standard_Integer aLen = aSeq->Length();
935
936   if (aLen == 0 && isMultiFile)
937     return aScript;
938
939   // Replace entries by the names
940   GEOM::GEOM_Gen_ptr geom = GetGeomEngine();
941   TColStd_SequenceOfAsciiString seqRemoved;
942   Resource_DataMapOfAsciiStringAsciiString mapRemoved;
943   Standard_Integer objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
944   TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("smeshObj_");
945
946   // Collect names of GEOM objects to exclude same names of SMESH objects
947   GEOM::string_array_var aGeomNames = geom->GetAllDumpNames();
948   int ign = 0, nbgn = aGeomNames->length();
949   for (; ign < nbgn; ign++) {
950     aName = aGeomNames[ign];
951     theObjectNames.Bind(aName, "1");
952   }
953
954   bool importGeom = false;
955   for (Standard_Integer i = 1; i <= aLen; i += 2) {
956     anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i) - 1);
957     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
958     // is a GEOM object?
959     aName = geom->GetDumpName( anEntry.ToCString() );
960     if (aName.IsEmpty()) {
961       // is a SMESH object
962       if (theObjectNames.IsBound(anEntry)) {
963         // The Object is in Study
964         aName = theObjectNames.Find(anEntry);
965         // check validity of aName
966         bool isValidName = fixPythonName( aName );
967         if (theObjectNames.IsBound(aName) && anEntry != theObjectNames(aName)) {
968           // diff objects have same name - make a new name by appending a digit
969           TCollection_AsciiString aName2;
970           Standard_Integer i = 0;
971           do {
972             aName2 = aName + "_" + ++i;
973           } while (theObjectNames.IsBound(aName2) && anEntry != theObjectNames(aName2));
974           aName = aName2;
975           isValidName = false;
976         }
977         if ( !isValidName )
978           theObjectNames(anEntry) = aName;
979
980       } else {
981         // Removed Object
982         do {
983           aName = aBaseName + (++objectCounter);
984         } while (theObjectNames.IsBound(aName));
985         seqRemoved.Append(aName);
986         mapRemoved.Bind(anEntry, "1");
987         theObjectNames.Bind(anEntry, aName);
988       }
989       theObjectNames.Bind(aName, anEntry); // to detect same name of diff objects
990     }
991     else
992     {
993       importGeom = true;
994     }
995     anUpdatedScript += aName;
996     aStart = aSeq->Value(i + 1) + 1;
997   }
998
999   // set initial part of aSript
1000   TCollection_AsciiString initPart = "import ";
1001   if ( isMultiFile )
1002     initPart += helper + "salome, ";
1003   initPart += aSmeshpy + ", SMESH, SALOMEDS\n";
1004   if ( importGeom && isMultiFile )
1005   {
1006     initPart += ("\n## import GEOM dump file ## \n"
1007                  "import string, os, sys, re\n"
1008                  "sys.path.insert( 0, os.path.dirname(__file__) )\n"
1009                  "exec(\"from \"+re.sub(\"SMESH$\",\"GEOM\",__name__)+\" import *\")\n");
1010   }
1011   anUpdatedScript.Insert ( 1, initPart );
1012
1013   // add final part of aScript
1014   if (aLen && aSeq->Value(aLen) < aScriptLength)
1015     anUpdatedScript += aScript.SubString(aSeq->Value(aLen) + 1, aScriptLength);
1016
1017   // Remove removed objects
1018   if ( seqRemoved.Length() > 0 ) {
1019     anUpdatedScript += "\n\t## some objects were removed";
1020     anUpdatedScript += "\n\taStudyBuilder = theStudy.NewBuilder()";
1021   }
1022   for (int ir = 1; ir <= seqRemoved.Length(); ir++) {
1023     if ( aRemovedObjIDs.count( seqRemoved.Value(ir) )) continue;
1024     anUpdatedScript += "\n\tSO = theStudy.FindObjectIOR(theStudy.ConvertObjectToIOR(";
1025     anUpdatedScript += seqRemoved.Value(ir);
1026     // for object wrapped by class of smesh.py
1027     anEntry = theObjectNames( seqRemoved.Value(ir) );
1028     if ( anEntry2AccessorMethod.IsBound( anEntry ) )
1029       anUpdatedScript += helper + "." + anEntry2AccessorMethod( anEntry );
1030     anUpdatedScript += "))\n\tif SO is not None: aStudyBuilder.RemoveObjectWithChildren(SO)";
1031   }
1032
1033   // Set object names
1034   anUpdatedScript += "\n\t## set object names";
1035 //   anUpdatedScript += "\n\t\tsmeshgui = salome.ImportComponentGUI(\"SMESH\")";
1036 //   anUpdatedScript += "\n\t\tsmeshgui.Init(theStudy._get_StudyId())";
1037 //   anUpdatedScript += "\n";
1038
1039   TCollection_AsciiString aGUIName;
1040   Resource_DataMapOfAsciiStringAsciiString mapEntries;
1041   for (Standard_Integer i = 1; i <= aLen; i += 2)
1042   {
1043     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
1044     aName   = geom->GetDumpName( anEntry.ToCString() );
1045     if (aName.IsEmpty() && // Not a GEOM object
1046         theNames.IsBound(anEntry) &&
1047         !aRemovedObjIDs.count(anEntry) && // a command creating anEntry was erased
1048         !mapEntries.IsBound(anEntry) && // Not yet processed
1049         !mapRemoved.IsBound(anEntry)) // Was not removed
1050     {
1051       aName    = theObjectNames.Find(anEntry);
1052       aGUIName = theNames.Find(anEntry);
1053       mapEntries.Bind(anEntry, aName);
1054       anUpdatedScript += helper + "\n\t" + aSMESHGen + ".SetName(" + aName;
1055       if ( anEntry2AccessorMethod.IsBound( anEntry ) )
1056         anUpdatedScript += helper + "." + anEntry2AccessorMethod( anEntry );
1057       anUpdatedScript += helper + ", '" + aGUIName + "')";
1058     }
1059   }
1060
1061   // Issue 0021249: removed (a similar block is dumped by SALOMEDSImpl_Study)
1062   //anUpdatedScript += "\n\tif salome.sg.hasDesktop():";
1063   //anUpdatedScript += "\n\t\tsalome.sg.updateObjBrowser(0)";
1064
1065   // -----------------------------------------------------------------
1066   // store visual properties of displayed objects
1067   // -----------------------------------------------------------------
1068
1069   if (isPublished)
1070   {
1071     //Output the script that sets up the visual parameters.
1072     CORBA::String_var compDataType = ComponentDataType();
1073     char* script = theStudy->GetDefaultScript( compDataType.in(), "\t");
1074     if (script && strlen(script) > 0) {
1075       anUpdatedScript += "\n\n\t### Store presentation parameters of displayed objects\n";
1076       anUpdatedScript += script;
1077       CORBA::string_free(script);
1078     }
1079   }
1080
1081   if( isMultiFile )
1082     anUpdatedScript += "\n\tpass";
1083   anUpdatedScript += "\n";
1084
1085   if( !isMultiFile ) // remove unnecessary tabulation
1086     RemoveTabulation( anUpdatedScript );
1087
1088   // -----------------------------------------------------------------
1089   // put string literals describing patterns into separate functions
1090   // -----------------------------------------------------------------
1091
1092   TCollection_AsciiString aLongString, aFunctionType;
1093   int where = 1;
1094   set< string > functionNameSet;
1095   while ( SMESH::TPythonDump::CutoutLongString( anUpdatedScript, where, aLongString, aFunctionType ))
1096   {
1097     // make a python string literal
1098     aLongString.Prepend(":\n\treturn '''\n");
1099     aLongString += "\n\t'''\n\tpass\n";
1100
1101     TCollection_AsciiString functionName;
1102
1103     // check if the function returning this literal is already defined
1104     int posAlready = anUpdatedScript.Location( aLongString, where, anUpdatedScript.Length() );
1105     if ( posAlready ) // already defined
1106     {
1107       // find the function name
1108       int functBeg = posAlready;
1109       char* script = (char*) anUpdatedScript.ToCString() + posAlready - 1; // look at ":" after "def fuction()"
1110       while ( *script != ' ' ) {
1111         script--;
1112         functBeg--;
1113       }
1114       functBeg++; // do not take ' '
1115       posAlready--; // do not take ':'
1116       functionName = anUpdatedScript.SubString( functBeg, posAlready );
1117     }
1118     else // not defined yet
1119     {
1120       // find a unique function name
1121       fixPythonName( aFunctionType );
1122       Standard_Integer nb = 0;
1123       do functionName = aFunctionType + "_" + ( nb++ ) + "()";
1124       while ( !functionNameSet.insert( functionName.ToCString() ).second );
1125
1126       // define function
1127       TCollection_AsciiString funDef = helper + "def " + functionName + aLongString;
1128       if ( isMultiFile )
1129       {
1130         anUpdatedScript += helper + "\n\n" + funDef;
1131       }
1132       else
1133       {
1134         funDef += "\n\n";
1135         anUpdatedScript.Insert( 1, funDef);
1136         where += funDef.Length();
1137       }
1138     }
1139     anUpdatedScript.InsertBefore( where, functionName ); // call function
1140   }
1141
1142   aValidScript = true;
1143
1144   return anUpdatedScript;
1145 }
1146
1147 //=============================================================================
1148 /*!
1149  *  GetNewPythonLines
1150  */
1151 //=============================================================================
1152 TCollection_AsciiString SMESH_Gen_i::GetNewPythonLines (int theStudyID)
1153 {
1154   TCollection_AsciiString aScript;
1155
1156   // Dump trace of API methods calls
1157   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
1158     Handle(TColStd_HSequenceOfAsciiString) aPythonScript = myPythonScripts[theStudyID];
1159     Standard_Integer istr, aLen = aPythonScript->Length();
1160     for (istr = 1; istr <= aLen; istr++) {
1161       aScript += "\n\t";
1162       aScript += aPythonScript->Value(istr);
1163     }
1164     aScript += "\n";
1165   }
1166
1167   return aScript;
1168 }
1169
1170 //=============================================================================
1171 /*!
1172  *  CleanPythonTrace
1173  */
1174 //=============================================================================
1175 void SMESH_Gen_i::CleanPythonTrace (int theStudyID)
1176 {
1177   TCollection_AsciiString aScript;
1178
1179   // Clean trace of API methods calls
1180   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
1181     myPythonScripts[theStudyID]->Clear();
1182   }
1183 }