Salome HOME
Dump Python. Add AddToCurrentPyScript(), AddArray(), AddObject()
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i_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_Gen_i.hxx"
8
9 #include <TColStd_HSequenceOfInteger.hxx>
10
11 //=======================================================================
12 //function : DumpPython
13 //purpose  : 
14 //=======================================================================
15 Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Object_ptr theStudy, 
16                                            CORBA::Boolean isPublished, 
17                                            CORBA::Boolean& isValidScript)
18 {
19   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
20   if (CORBA::is_nil(aStudy))
21     return new Engines::TMPFile(0);   
22
23   SALOMEDS::SObject_var aSO = aStudy->FindComponent(ComponentDataType());
24   if (CORBA::is_nil(aSO))
25     return new Engines::TMPFile(0);  
26
27   // Map study entries to object names
28   Resource_DataMapOfAsciiStringAsciiString aMap;
29   TCollection_AsciiString s ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
30
31   SALOMEDS::ChildIterator_var Itr = aStudy->NewChildIterator(aSO);
32   for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
33     SALOMEDS::SObject_var aValue = Itr->Value();
34
35     TCollection_AsciiString aName (aValue->GetName());
36     int p, p2 = 1, e = aName.Length();
37     while ((p = aName.FirstLocationNotInSet(s, p2, e))) {
38       aName.SetValue(p, '_');
39       p2 = p;
40     }  
41     aMap.Bind(TCollection_AsciiString(aValue->GetID()), aName);
42   }
43
44   // Get trace of restored study
45   //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
46   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
47   SALOMEDS::GenericAttribute_var anAttr =
48     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
49
50   char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
51   TCollection_AsciiString aSavedTrace (oldValue);
52
53   // Add trace of API methods calls and replace study entries by names
54   bool aValidScript;
55   //TCollection_AsciiString aScript = myGen.DumpPython
56   TCollection_AsciiString aScript = DumpPython_impl
57     (aStudy->StudyId(), aMap, isPublished, aValidScript, aSavedTrace);
58
59   int aLen = aScript.Length(); 
60   unsigned char* aBuffer = new unsigned char[aLen+1];
61   strcpy((char*)aBuffer, aScript.ToCString());
62
63   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
64   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aLen+1, aLen+1, anOctetBuf, 1); 
65   isValidScript = aValidScript;
66
67   return aStreamFile._retn(); 
68 }
69
70 //=============================================================================
71 /*!
72  *  AddToPythonScript
73  */
74 //=============================================================================
75 void SMESH_Gen_i::AddToPythonScript (int theStudyID, const TCollection_AsciiString& theString)
76 {
77   if (myPythonScripts.find(theStudyID) == myPythonScripts.end()) {
78     myPythonScripts[theStudyID] = new TColStd_HSequenceOfAsciiString;
79   }
80   myPythonScripts[theStudyID]->Append(theString);
81 }
82
83 //=======================================================================
84 //function : AddToCurrentPyScript
85 //purpose  : 
86 //=======================================================================
87
88 void SMESH_Gen_i::AddToCurrentPyScript (const TCollection_AsciiString& theString)
89 {
90   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
91   aSMESHGen->AddToPythonScript(aSMESHGen->GetCurrentStudy()->StudyId(), theString);
92 }
93
94
95 //=======================================================================
96 //function : AddObject
97 //purpose  : add object to script string
98 //=======================================================================
99
100 TCollection_AsciiString& SMESH_Gen_i::AddObject(TCollection_AsciiString& theStr,
101                                                 CORBA::Object_ptr        theObject)
102 {
103   GEOM::GEOM_Object_var geomObj = GEOM::GEOM_Object::_narrow( theObject );
104   if ( !geomObj->_is_nil() ) {
105     theStr += "salome.IDToObject(\"";
106     theStr += geomObj->GetStudyEntry();
107     theStr += "\")";
108   }
109   else {
110     SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
111     SALOMEDS::SObject_var aSO =
112       aSMESHGen->ObjectToSObject(aSMESHGen->GetCurrentStudy(), theObject);
113     if ( !aSO->_is_nil() )
114       theStr += aSO->GetID();
115     else if ( !CORBA::is_nil( theObject ) )
116       theStr += aSMESHGen->GetORB()->object_to_string( theObject );
117     else
118       theStr += "None";
119   }
120   return theStr;
121 }
122
123 //=======================================================================
124 //function : SavePython
125 //purpose  : 
126 //=======================================================================
127 void SMESH_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
128 {
129   // Dump trace of API methods calls
130   TCollection_AsciiString aScript = GetNewPythonLines(theStudy->StudyId());
131
132   // Check contents of PythonObject attribute
133   SALOMEDS::SObject_var aSO = theStudy->FindComponent(ComponentDataType());
134   //SALOMEDS::SObject_var aSO = SMESH_Gen_i::ObjectToSObject(theStudy, _this());
135   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
136   SALOMEDS::GenericAttribute_var anAttr =
137     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
138
139   char* oldValue = SALOMEDS::AttributePythonObject::_narrow(anAttr)->GetObject();
140   TCollection_AsciiString oldScript (oldValue);
141
142   if (oldScript.Length() > 0) {
143     oldScript += "\n";
144     oldScript += aScript;
145   } else {
146     oldScript = aScript;
147   }
148
149   // Store in PythonObject attribute
150   SALOMEDS::AttributePythonObject::_narrow(anAttr)->SetObject(oldScript.ToCString(), 1);
151
152   // Clean trace of API methods calls
153   CleanPythonTrace(theStudy->StudyId());
154 }
155
156
157 // impl
158
159
160 //=============================================================================
161 /*!
162  *  FindEntries: Returns a sequence of start/end positions of entries in the string
163  */
164 //=============================================================================
165 Handle(TColStd_HSequenceOfInteger) FindEntries (TCollection_AsciiString& theString)
166 {
167   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
168   Standard_Integer aLen = theString.Length();
169   Standard_Boolean isFound = Standard_False;
170
171   char* arr = theString.ToCString();
172   Standard_Integer i = 0, j;
173
174   while(i < aLen) {
175     int c = (int)arr[i];
176     j = i+1;
177     if(c >= 48 && c <= 57) { //Is digit?
178  
179       isFound = Standard_False;
180       while((j < aLen) && ((c >= 48 && c <= 57) || c == 58) ) { //Check if it is an entry
181         c = (int)arr[j++];  
182         if(c == 58) isFound = Standard_True;
183       }
184
185       if (isFound) {
186         int prev = (i < 1) ? 0 : (int)arr[i - 1];
187         // last char should be a diggit,
188         // previous char should not be '"'.
189         if (arr[j-2] != 58 && prev != 34) {
190           aSeq->Append(i+1); // +1 because AsciiString starts from 1
191           aSeq->Append(j-1);
192         }
193       }
194     }
195
196     i = j;
197   }
198
199   return aSeq;
200 }
201
202 //=============================================================================
203 /*!
204  *  DumpPython
205  */
206 //=============================================================================
207 TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
208                         (int theStudyID, 
209                          Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
210                          bool isPublished, 
211                          bool& aValidScript,
212                          const TCollection_AsciiString& theSavedTrace)
213 {
214   TCollection_AsciiString aScript;
215   aScript += "import salome\n";
216   aScript += "import geompy\n\n";
217   aScript += "import SMESH\n";
218   aScript += "import StdMeshers\n\n";
219   aScript += "def RebuildData(theStudy):";
220   aScript += "\n\tsmesh = salome.lcc.FindOrLoadComponent(\"FactoryServer\", \"SMESH\")";
221   aScript += "\n\tsmesh.SetCurrentStudy(theStudy)";
222
223   // Dump trace of restored study
224   if (theSavedTrace.Length() > 0) {
225     aScript += "\n";
226     aScript += theSavedTrace;
227   }
228
229   // Dump trace of API methods calls
230   TCollection_AsciiString aNewLines = GetNewPythonLines(theStudyID);
231   if (aNewLines.Length() > 0) {
232     aScript += "\n";
233     aScript += aNewLines;
234   }
235 //  if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
236 //    aScript += "\n";
237 //    Handle(TColStd_HSequenceOfAsciiString) aPythonScript = myPythonScripts[theStudyID];
238 //    Standard_Integer istr, aLen = aPythonScript->Length();
239 //    for (istr = 1; istr <= aLen; istr++) {
240 //      aScript += "\n\t";
241 //      aScript += aPythonScript->Value(istr);
242 //    }
243 //    aScript += "\n";
244 //  }
245
246   // Find entries to be replaced by names
247   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
248   Standard_Integer aLen = aSeq->Length();
249
250   if (aLen == 0)
251     return aScript;
252
253   // Replace entries by the names
254   Resource_DataMapOfAsciiStringAsciiString aNames;
255   Standard_Integer objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
256   TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("geomObj_");
257
258   for (Standard_Integer i = 1; i <= aLen; i += 2) {
259     anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i) - 1);
260     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
261     if (theObjectNames.IsBound(anEntry)) {
262       aName = theObjectNames.Find(anEntry);
263       if (theObjectNames.IsBound(aName) && anEntry != theObjectNames(aName)) {
264         // diff objects have same name - make a new name
265         TCollection_AsciiString aName2;
266         Standard_Integer i = 0;
267         do {
268           aName2 = aName + "_" + ++i;
269         } while (theObjectNames.IsBound(aName2) && anEntry != theObjectNames(aName2));
270         aName = aName2;
271         theObjectNames(anEntry) = aName;
272       }
273     } else {
274       do {
275         aName = aBaseName + TCollection_AsciiString(++objectCounter);
276       } while (theObjectNames.IsBound(aName));
277       theObjectNames.Bind(anEntry, aName);
278     }
279     theObjectNames.Bind(aName, anEntry); // to detect same name of diff objects
280
281     anUpdatedScript += aName;
282     aNames.Bind(aName, "1");
283     aStart = aSeq->Value(i + 1) + 1;
284   }
285
286   // add final part of the script
287   if (aSeq->Value(aLen) < aScriptLength)
288     anUpdatedScript += aScript.SubString(aSeq->Value(aLen) + 1, aScriptLength);
289
290   // Set object names
291   anUpdatedScript += "\n\tisGUIMode = 1";
292   anUpdatedScript += "\n\tif isGUIMode:";
293   anUpdatedScript += "\n\t\tsmeshgui = salome.ImportComponentGUI(\"SMESH\")";
294   anUpdatedScript += "\n\t\tsmeshgui.Init(theStudy._get_StudyId())";
295   anUpdatedScript += "\n";
296
297   Resource_DataMapOfAsciiStringAsciiString mapEntries;
298   for (Standard_Integer i = 1; i <= aLen; i += 2) {
299     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
300     if (theObjectNames.IsBound(anEntry) && !mapEntries.IsBound(anEntry)) {
301       aName = theObjectNames.Find(anEntry);
302       mapEntries.Bind(anEntry, aName);
303       anUpdatedScript += "\n\t\tsmeshgui.SetName(salome.ObjectToID(";
304       anUpdatedScript += aName + "), \"" + aName + "\")";
305       //anUpdatedScript += "\n\t\tsmeshgui.SetName(\"";
306       //anUpdatedScript += anEntry + "\", \"" + aName + "\")";
307     }
308   }
309   anUpdatedScript += "\n\n\t\tsalome.sg.updateObjBrowser(0)";
310
311   anUpdatedScript += "\n\n\tpass\n";
312
313   aValidScript = true;
314
315   return anUpdatedScript;
316 }
317
318 //=============================================================================
319 /*!
320  *  GetNewPythonLines
321  */
322 //=============================================================================
323 TCollection_AsciiString SMESH_Gen_i::GetNewPythonLines (int theStudyID)
324 {
325   TCollection_AsciiString aScript;
326
327   // Dump trace of API methods calls
328   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
329     Handle(TColStd_HSequenceOfAsciiString) aPythonScript = myPythonScripts[theStudyID];
330     Standard_Integer istr, aLen = aPythonScript->Length();
331     for (istr = 1; istr <= aLen; istr++) {
332       aScript += "\n\t";
333       aScript += aPythonScript->Value(istr);
334     }
335     aScript += "\n";
336   }
337
338   return aScript;
339 }
340
341 //=============================================================================
342 /*!
343  *  CleanPythonTrace
344  */
345 //=============================================================================
346 void SMESH_Gen_i::CleanPythonTrace (int theStudyID)
347 {
348   TCollection_AsciiString aScript;
349
350   // Clean trace of API methods calls
351   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
352     myPythonScripts[theStudyID]->Clear();
353   }
354 }