]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESH_I/SMESH_DumpPython.cxx
Salome HOME
PythonDump for SMESH Controls / Filter
[modules/smesh.git] / src / SMESH_I / SMESH_DumpPython.cxx
1 // File    : SMESH_Gen_i_DumpPython.cxx
2 // Created : Thu Mar 24 17:17:59 2005
3 // Author  : Julia DOROVSKIKH
4 // Module  : SMESH
5 // $Header : $
6
7 #include "SMESH_PythonDump.hxx"
8 #include "SMESH_Gen_i.hxx"
9 #include "SMESH_Filter_i.hxx"
10
11 #include <TColStd_HSequenceOfInteger.hxx>
12
13 namespace SMESH
14 {
15   TCollection_AsciiString& 
16   operator<<(TCollection_AsciiString& theString, const char* theArg){
17     theString += Standard_CString(theArg);
18     return theString;
19   }
20
21   TCollection_AsciiString& 
22   operator<<(TCollection_AsciiString& theString, int theArg){
23     theString += TCollection_AsciiString(theArg);
24     return theString;
25   }
26
27   TCollection_AsciiString& 
28   operator<<(TCollection_AsciiString& theString, float theArg){
29     theString += TCollection_AsciiString(theArg);
30     return theString;
31   }
32
33   TCollection_AsciiString& 
34   operator<<(TCollection_AsciiString& theString, 
35              const SMESH::long_array& theArg)
36   {
37     theString<<"[ ";
38     CORBA::Long i = 1, iEnd = theArg.length();
39     for(; i <= iEnd; i++) {
40       theString<<int(theArg[i-1]);
41       if(i < iEnd)
42         theString<< ", ";
43     }
44     theString<<" ]";
45     return theString;
46   }
47
48
49   TCollection_AsciiString& 
50   operator<<(TCollection_AsciiString& theString, 
51              CORBA::Object_ptr theArg)
52   {
53     CORBA::String_var aString("None");
54     SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
55     SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
56     SALOMEDS::SObject_var aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
57     if(!aSObject->_is_nil()){
58       aString = aSObject->GetID();
59     }else if(!CORBA::is_nil(theArg)){
60       aString = SMESH_Gen_i::GetORB()->object_to_string(theArg);
61     }
62     theString<<aString.in();
63     return theString;
64   }
65
66   TCollection_AsciiString& 
67   operator<<(TCollection_AsciiString& theString, 
68              SMESH::FilterLibrary_i* theArg)
69   {
70     theString += TCollection_AsciiString("aFilterLibrary_");
71     theString += TCollection_AsciiString(int(theArg));
72     return theString;
73   }
74
75   TCollection_AsciiString& 
76   operator<<(TCollection_AsciiString& theString, 
77              SMESH::FilterManager_i* theArg)
78   {
79     theString += TCollection_AsciiString("aFilterManager_");
80     theString += TCollection_AsciiString(int(theArg));
81     return theString;
82   }
83
84   TCollection_AsciiString& 
85   operator<<(TCollection_AsciiString& theString, 
86              SMESH::Filter_i* theArg)
87   {
88     theString += TCollection_AsciiString("aFilter_");
89     theString += TCollection_AsciiString(int(theArg));
90     return theString;
91   }
92
93   TCollection_AsciiString& 
94   operator<<(TCollection_AsciiString& theString, 
95              SMESH::Functor_i* theArg)
96   {
97     FunctorType aFunctorType = theArg->GetFunctorType();
98     switch(aFunctorType){
99     case FT_AspectRatio:
100       theString += TCollection_AsciiString("anAspectRatio");
101       break;
102     case FT_AspectRatio3D:
103       theString += TCollection_AsciiString("anAspectRatio3D");
104       break;
105     case FT_Warping:
106       theString += TCollection_AsciiString("aWarping");
107       break;
108     case FT_MinimumAngle:
109       theString += TCollection_AsciiString("aMinimumAngle");
110       break;
111     case FT_Taper:
112       theString += TCollection_AsciiString("aTaper");
113       break;
114     case FT_Skew:
115       theString += TCollection_AsciiString("aSkew");
116       break;
117     case FT_Area:
118       theString += TCollection_AsciiString("aArea");
119       break;
120     case FT_FreeBorders:
121       theString += TCollection_AsciiString("aFreeBorders");
122       break;
123     case FT_FreeEdges:
124       theString += TCollection_AsciiString("aFreeEdges");
125       break;
126     case FT_MultiConnection:
127       theString += TCollection_AsciiString("aMultiConnection");
128       break;
129     case FT_MultiConnection2D:
130       theString += TCollection_AsciiString("aMultiConnection2D");
131       break;
132     case FT_Length:
133       theString += TCollection_AsciiString("aLength");
134       break;
135     case FT_Length2D:
136       theString += TCollection_AsciiString("aLength");
137       break;
138     case FT_BelongToGeom:
139       theString += TCollection_AsciiString("aBelongToGeom");
140       break;
141     case FT_BelongToPlane:
142       theString += TCollection_AsciiString("aBelongToPlane");
143       break;
144     case FT_BelongToCylinder:
145       theString += TCollection_AsciiString("aBelongToCylinder");
146       break;
147     case FT_LyingOnGeom:
148       theString += TCollection_AsciiString("aLyingOnGeom");
149       break;
150     case FT_RangeOfIds:
151       theString += TCollection_AsciiString("aRangeOfIds");
152       break;
153     case FT_BadOrientedVolume:
154       theString += TCollection_AsciiString("aBadOrientedVolume");
155       break;
156     case FT_LessThan:
157       theString += TCollection_AsciiString("aLessThan");
158       break;
159     case FT_MoreThan:
160       theString += TCollection_AsciiString("aMoreThan");
161       break;
162     case FT_EqualTo:
163       theString += TCollection_AsciiString("anEqualTo");
164       break;
165     case FT_LogicalNOT:
166       theString += TCollection_AsciiString("aLogicalNOT");
167       break;
168     case FT_LogicalAND:
169       theString += TCollection_AsciiString("aLogicalAND");
170       break;
171     case FT_LogicalOR:
172       theString += TCollection_AsciiString("aLogicalOR");
173       break;
174     case FT_Undefined:
175       theString += TCollection_AsciiString("anUndefined");
176       break;
177     }
178     theString += Standard_CString("_");
179     theString += TCollection_AsciiString(int(theArg));
180     return theString;
181   }
182
183   size_t TPythonDump::myCounter = 0;
184
185   TPythonDump::
186   TPythonDump()
187   {
188     ++myCounter;
189   }
190   TPythonDump::
191   ~TPythonDump()
192   {
193     if(--myCounter == 0){
194       SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
195       SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
196       if(!aStudy->_is_nil()){
197         aSMESHGen->AddToPythonScript(aStudy->StudyId(),myString);
198       }
199     }
200   }
201 }
202
203 //=======================================================================
204 //function : DumpPython
205 //purpose  : 
206 //=======================================================================
207 Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Object_ptr theStudy,
208                                            CORBA::Boolean isPublished,
209                                            CORBA::Boolean& isValidScript)
210 {
211   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
212   if (CORBA::is_nil(aStudy))
213     return new Engines::TMPFile(0);
214
215   SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
216   if (CORBA::is_nil(aSO))
217     return new Engines::TMPFile(0);
218
219   // Map study entries to object names
220   Resource_DataMapOfAsciiStringAsciiString aMap;
221   TCollection_AsciiString s ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
222
223   SALOMEDS::ChildIterator_var Itr = aStudy->NewChildIterator(aSO);
224   for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
225     SALOMEDS::SObject_var aValue = Itr->Value();
226
227     TCollection_AsciiString aName (aValue->GetName());
228     if (aName.Length() > 0) {
229       int p, p2 = 1, e = aName.Length();
230       while ((p = aName.FirstLocationNotInSet(s, p2, e))) {
231         aName.SetValue(p, '_');
232         p2 = p;
233       }
234       aMap.Bind(TCollection_AsciiString(aValue->GetID()), aName);
235     }
236   }
237
238   // Get trace of restored study
239   //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
240   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
241   SALOMEDS::GenericAttribute_var anAttr =
242     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
243
244   char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
245   TCollection_AsciiString aSavedTrace (oldValue);
246
247   // Add trace of API methods calls and replace study entries by names
248   bool aValidScript;
249   //TCollection_AsciiString aScript = myGen.DumpPython
250   TCollection_AsciiString aScript = DumpPython_impl
251     (aStudy->StudyId(), aMap, isPublished, aValidScript, aSavedTrace);
252
253   int aLen = aScript.Length(); 
254   unsigned char* aBuffer = new unsigned char[aLen+1];
255   strcpy((char*)aBuffer, aScript.ToCString());
256
257   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
258   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aLen+1, aLen+1, anOctetBuf, 1); 
259   isValidScript = aValidScript;
260
261   return aStreamFile._retn(); 
262 }
263
264 //=============================================================================
265 /*!
266  *  AddToPythonScript
267  */
268 //=============================================================================
269 void SMESH_Gen_i::AddToPythonScript (int theStudyID, const TCollection_AsciiString& theString)
270 {
271   if (myPythonScripts.find(theStudyID) == myPythonScripts.end()) {
272     myPythonScripts[theStudyID] = new TColStd_HSequenceOfAsciiString;
273   }
274   myPythonScripts[theStudyID]->Append(theString);
275 }
276
277 //=============================================================================
278 /*!
279  *  RemoveLastFromPythonScript
280  */
281 //=============================================================================
282 void SMESH_Gen_i::RemoveLastFromPythonScript (int theStudyID)
283 {
284   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
285     int aLen = myPythonScripts[theStudyID]->Length();
286     myPythonScripts[theStudyID]->Remove(aLen);
287   }
288 }
289
290 //=======================================================================
291 //function : AddToCurrentPyScript
292 //purpose  : 
293 //=======================================================================
294
295 void SMESH_Gen_i::AddToCurrentPyScript (const TCollection_AsciiString& theString)
296 {
297   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
298   SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy();
299   if (aStudy->_is_nil()) return;
300   aSMESHGen->AddToPythonScript(aStudy->StudyId(), theString);
301 }
302
303
304 //=======================================================================
305 //function : AddObject
306 //purpose  : add object to script string
307 //=======================================================================
308
309 TCollection_AsciiString& SMESH_Gen_i::AddObject(TCollection_AsciiString& theStr,
310                                                 CORBA::Object_ptr        theObject)
311 {
312   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
313   SALOMEDS::SObject_var aSO =
314     aSMESHGen->ObjectToSObject(aSMESHGen->GetCurrentStudy(), theObject);
315   if ( !aSO->_is_nil() )
316     theStr += aSO->GetID();
317   else if ( !CORBA::is_nil( theObject ) )
318     theStr += GetORB()->object_to_string( theObject );
319   else
320     theStr += "None";
321
322   return theStr;
323 }
324
325 //=======================================================================
326 //function : SavePython
327 //purpose  : 
328 //=======================================================================
329 void SMESH_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
330 {
331   // Dump trace of API methods calls
332   TCollection_AsciiString aScript = GetNewPythonLines(theStudy->StudyId());
333
334   // Check contents of PythonObject attribute
335   SALOMEDS::SObject_var aSO = theStudy->FindComponent(ComponentDataType());
336   //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
337   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
338   SALOMEDS::GenericAttribute_var anAttr =
339     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
340
341   char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
342   TCollection_AsciiString oldScript (oldValue);
343
344   if (oldScript.Length() > 0) {
345     oldScript += "\n";
346     oldScript += aScript;
347   } else {
348     oldScript = aScript;
349   }
350
351   // Store in PythonObject attribute
352   SALOMEDS::AttributePythonObject::_narrow(anAttr)->SetObject(oldScript.ToCString(), 1);
353
354   // Clean trace of API methods calls
355   CleanPythonTrace(theStudy->StudyId());
356 }
357
358
359 // impl
360
361
362 //=============================================================================
363 /*!
364  *  FindEntries: Returns a sequence of start/end positions of entries in the string
365  */
366 //=============================================================================
367 Handle(TColStd_HSequenceOfInteger) FindEntries (TCollection_AsciiString& theString)
368 {
369   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
370   Standard_Integer aLen = theString.Length();
371   Standard_Boolean isFound = Standard_False;
372
373   char* arr = theString.ToCString();
374   Standard_Integer i = 0, j;
375
376   while(i < aLen) {
377     int c = (int)arr[i];
378     j = i+1;
379     if(c >= 48 && c <= 57) { //Is digit?
380  
381       isFound = Standard_False;
382       while((j < aLen) && ((c >= 48 && c <= 57) || c == 58) ) { //Check if it is an entry
383         c = (int)arr[j++];  
384         if(c == 58) isFound = Standard_True;
385       }
386
387       if (isFound) {
388         int prev = (i < 1) ? 0 : (int)arr[i - 1];
389         // last char should be a diggit,
390         // previous char should not be '"'.
391         if (arr[j-2] != 58 && prev != 34) {
392           aSeq->Append(i+1); // +1 because AsciiString starts from 1
393           aSeq->Append(j-1);
394         }
395       }
396     }
397
398     i = j;
399   }
400
401   return aSeq;
402 }
403
404 //=============================================================================
405 /*!
406  *  DumpPython
407  */
408 //=============================================================================
409 TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
410                         (int theStudyID, 
411                          Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
412                          bool isPublished, 
413                          bool& aValidScript,
414                          const TCollection_AsciiString& theSavedTrace)
415 {
416   TCollection_AsciiString aScript;
417   aScript += "import salome\n";
418   aScript += "import geompy\n\n";
419   aScript += "import SMESH\n";
420   aScript += "import StdMeshers\n\n";
421   aScript += "#import GEOM module\n";
422   aScript += "import string\n";
423   aScript += "import os\n";
424   aScript += "import sys\n";
425   aScript += "sys.path.append( os.path.dirname(__file__) )\n";
426   aScript += "exec(\"from \"+string.replace(__name__,\"SMESH\",\"GEOM\")+\" import *\")\n\n";
427   
428   aScript += "def RebuildData(theStudy):";
429   aScript += "\n\tsmesh = salome.lcc.FindOrLoadComponent(\"FactoryServer\", \"SMESH\")";
430   if ( isPublished )
431     aScript += "\n\tsmesh.SetCurrentStudy(theStudy)";
432   else
433     aScript += "\n\tsmesh.SetCurrentStudy(None)";
434
435   TCollection_AsciiString globalVars;
436
437   // Dump trace of restored study
438   if (theSavedTrace.Length() > 0) {
439     aScript += "\n";
440     aScript += theSavedTrace;
441   }
442
443   // Dump trace of API methods calls
444   TCollection_AsciiString aNewLines = GetNewPythonLines(theStudyID);
445   if (aNewLines.Length() > 0) {
446     aScript += "\n";
447     aScript += aNewLines;
448   }
449
450   // Find entries to be replaced by names
451   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
452   Standard_Integer aLen = aSeq->Length();
453
454   if (aLen == 0)
455     return aScript;
456
457   // Replace entries by the names
458   GEOM::GEOM_Gen_ptr geom = GetGeomEngine();
459   TColStd_SequenceOfAsciiString seqRemoved;
460   Resource_DataMapOfAsciiStringAsciiString mapRemoved;
461   Resource_DataMapOfAsciiStringAsciiString aNames;
462   Standard_Integer objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
463   TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("smeshObj_");
464
465   for (Standard_Integer i = 1; i <= aLen; i += 2) {
466     anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i) - 1);
467     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
468     if (theObjectNames.IsBound(anEntry)) {
469       aName = theObjectNames.Find(anEntry);
470       if (theObjectNames.IsBound(aName) && anEntry != theObjectNames(aName)) {
471         // diff objects have same name - make a new name
472         TCollection_AsciiString aName2;
473         Standard_Integer i = 0;
474         do {
475           aName2 = aName + "_" + ++i;
476         } while (theObjectNames.IsBound(aName2) && anEntry != theObjectNames(aName2));
477         aName = aName2;
478         theObjectNames(anEntry) = aName;
479       }
480     } else {
481       // is a GEOM object?
482       aName = geom->GetDumpName( anEntry.ToCString() );
483       if ( aName.IsEmpty() ) {
484       // ? Removed Object ?
485         do {
486           aName = aBaseName + TCollection_AsciiString(++objectCounter);
487         } while (theObjectNames.IsBound(aName));
488         seqRemoved.Append(aName);
489         mapRemoved.Bind(anEntry, "1");
490       }
491       theObjectNames.Bind(anEntry, aName);
492     }
493     theObjectNames.Bind(aName, anEntry); // to detect same name of diff objects
494
495     anUpdatedScript += aName;
496     aNames.Bind(aName, "1");
497     aStart = aSeq->Value(i + 1) + 1;
498   }
499
500   // add final part of aScript
501   if (aSeq->Value(aLen) < aScriptLength)
502     anUpdatedScript += aScript.SubString(aSeq->Value(aLen) + 1, aScriptLength);
503
504   // Remove removed objects
505   anUpdatedScript += "\n\taStudyBuilder = theStudy.NewBuilder()";
506   for (int ir = 1; ir <= seqRemoved.Length(); ir++) {
507     anUpdatedScript += "\n\tSO = theStudy.FindObjectIOR(theStudy.ConvertObjectToIOR(";
508     anUpdatedScript += seqRemoved.Value(ir);
509     anUpdatedScript += "))\n\tif SO is not None: aStudyBuilder.RemoveObjectWithChildren(SO)";
510   }
511   anUpdatedScript += "\n";
512
513   // Set object names
514   anUpdatedScript += "\n\tisGUIMode = ";
515   anUpdatedScript += isPublished;
516   anUpdatedScript += "\n\tif isGUIMode:";
517   anUpdatedScript += "\n\t\tsmeshgui = salome.ImportComponentGUI(\"SMESH\")";
518   anUpdatedScript += "\n\t\tsmeshgui.Init(theStudy._get_StudyId())";
519   anUpdatedScript += "\n";
520
521   Resource_DataMapOfAsciiStringAsciiString mapEntries;
522   for (Standard_Integer i = 1; i <= aLen; i += 2) {
523     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
524     if (theObjectNames.IsBound(anEntry) &&
525         !mapEntries.IsBound(anEntry) &&
526         !mapRemoved.IsBound(anEntry)) {
527       aName = theObjectNames.Find(anEntry);
528       mapEntries.Bind(anEntry, aName);
529       anUpdatedScript += "\n\t\tsmeshgui.SetName(salome.ObjectToID(";
530       anUpdatedScript += aName + "), \"" + aName + "\")";
531     }
532   }
533   anUpdatedScript += "\n\n\t\tsalome.sg.updateObjBrowser(0)";
534
535   anUpdatedScript += "\n\n\tpass\n";
536
537   aValidScript = true;
538
539   return anUpdatedScript;
540 }
541
542 //=============================================================================
543 /*!
544  *  GetNewPythonLines
545  */
546 //=============================================================================
547 TCollection_AsciiString SMESH_Gen_i::GetNewPythonLines (int theStudyID)
548 {
549   TCollection_AsciiString aScript;
550
551   // Dump trace of API methods calls
552   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
553     Handle(TColStd_HSequenceOfAsciiString) aPythonScript = myPythonScripts[theStudyID];
554     Standard_Integer istr, aLen = aPythonScript->Length();
555     for (istr = 1; istr <= aLen; istr++) {
556       aScript += "\n\t";
557       aScript += aPythonScript->Value(istr);
558     }
559     aScript += "\n";
560   }
561
562   return aScript;
563 }
564
565 //=============================================================================
566 /*!
567  *  CleanPythonTrace
568  */
569 //=============================================================================
570 void SMESH_Gen_i::CleanPythonTrace (int theStudyID)
571 {
572   TCollection_AsciiString aScript;
573
574   // Clean trace of API methods calls
575   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
576     myPythonScripts[theStudyID]->Clear();
577   }
578 }