Salome HOME
Variables naming.
[modules/hydro.git] / src / HYDROData / HYDROData_Document.cxx
1
2 #include <HYDROData_Document.h>
3 #include <HYDROData_Application.h>
4 #include <HYDROData_Iterator.h>
5 #include <HYDROData_Tool.h>
6
7 #include <TDataStd_Integer.hxx>
8
9 #include <TDF_Delta.hxx>
10
11 #include <QFile>
12 #include <QStringList>
13 #include <QTextStream>
14
15 IMPLEMENT_STANDARD_HANDLE(HYDROData_Document,MMgt_TShared)
16 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Document,MMgt_TShared)
17
18 #define PYTHON_DOC_NAME "hydro_doc"
19
20 static const int UNDO_LIMIT = 10; // number of possible undo operations in the module
21
22 static const int TAG_PROPS = 1; // general properties tag
23 static const int TAG_PROPS_NEW_ID = 1; // general properties: tag for storage of the new object ID
24 static const int TAG_OBJECTS = 2; // tag of the objects sub-tree
25 static const int TAG_HISTORY = 3; // tag of the history sub-tree (Root for History)
26
27 using namespace std;
28
29 Handle(HYDROData_Document) HYDROData_Document::Document(const int theStudyID)
30 {
31   Handle(HYDROData_Document) aResult = 
32     HYDROData_Application::GetApplication()->GetDocument(theStudyID);
33   if (aResult.IsNull()) {
34     aResult = new HYDROData_Document();
35     HYDROData_Application::GetApplication()->AddDocument(theStudyID, aResult);
36   }
37   return aResult;
38 }
39
40 Handle(HYDROData_Document) HYDROData_Document::Document(
41   const TDF_Label& theObjectLabel )
42 {
43   Handle(HYDROData_Document) aResDoc;
44   if ( theObjectLabel.IsNull() )
45     return aResDoc;
46
47   Handle(TDocStd_Document) anObjDoc;
48   try
49   {
50     anObjDoc = TDocStd_Document::Get( theObjectLabel );
51   }
52   catch( ... )
53   {
54   }
55
56   if ( anObjDoc.IsNull() )
57     return aResDoc;
58
59   HYDROData_Application* anApp = HYDROData_Application::GetApplication();
60
61   DataMapOfStudyIDDocument::Iterator aMapIt( anApp->myDocuments );
62   for ( ; aMapIt.More(); aMapIt.Next() )
63   {
64     Handle(HYDROData_Document) anAppDoc = aMapIt.Value();
65     if ( anAppDoc.IsNull() || anAppDoc->myDoc != anObjDoc )
66       continue;
67
68     aResDoc = anAppDoc;
69     break;
70   }
71
72   return aResDoc;
73 }
74
75 bool HYDROData_Document::HasDocument(const int theStudyID)
76 {
77   Handle(HYDROData_Document) aResult = 
78     HYDROData_Application::GetApplication()->GetDocument(theStudyID);
79   return !aResult.IsNull();
80 }
81
82 bool HYDROData_Document::DocumentId(const Handle(HYDROData_Document)& theDocument,
83                                     int&                              theDocId )
84 {
85   return HYDROData_Application::GetApplication()->GetDocumentId(theDocument, theDocId);
86 }
87
88 Data_DocError HYDROData_Document::Load(const char* theFileName, const int theStudyID)
89 {
90   Handle(TDocStd_Document) aResult;
91   TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
92   PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1;
93   try
94   {
95     aStatus = HYDROData_Application::GetApplication()->Open (aPath, aResult);
96   }
97   catch (Standard_Failure)
98   {}
99   if (!aResult.IsNull()) {
100     aResult->SetUndoLimit(UNDO_LIMIT);
101     HYDROData_Application::GetApplication()->AddDocument(theStudyID, new HYDROData_Document(aResult));
102   }
103   // recognize error
104   Data_DocError anError;
105   switch(aStatus) {
106   case PCDM_RS_OK:
107     anError = DocError_OK;
108     break;
109   case PCDM_RS_NoDriver:
110   case PCDM_RS_UnknownFileDriver:
111   case PCDM_RS_NoSchema:
112   case PCDM_RS_DriverFailure:
113   case PCDM_RS_WrongResource:
114     anError = DocError_ResourcesProblem;
115     break;
116   case PCDM_RS_OpenError:
117   case PCDM_RS_NoDocument:
118   case PCDM_RS_WrongStreamMode:
119   case PCDM_RS_PermissionDenied:
120     anError = DocError_CanNotOpen;
121     break;
122   case PCDM_RS_NoVersion:
123     anError = DocError_InvalidVersion;
124     break;
125   case PCDM_RS_ExtensionFailure:
126   case PCDM_RS_FormatFailure:
127   case PCDM_RS_TypeFailure:
128   case PCDM_RS_TypeNotFoundInSchema:
129   case PCDM_RS_UnrecognizedFileFormat:
130     anError = DocError_InvalidFormat;
131     break;
132   case PCDM_RS_MakeFailure:
133   default:
134     anError = DocError_UnknownProblem;
135     break;
136   }
137   return anError;
138 }
139
140 Data_DocError HYDROData_Document::Save(const char* theFileName)
141 {
142   TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
143   PCDM_StoreStatus aStatus;
144   try {
145     aStatus = HYDROData_Application::GetApplication()->SaveAs (myDoc, aPath);
146   }
147   catch (Standard_Failure) {}
148   myTransactionsAfterSave = 0;
149   Standard::Purge(); // Release free memory
150
151   // recognize error
152   Data_DocError anError;
153   switch(aStatus) {
154   case PCDM_SS_OK:
155     anError = DocError_OK;
156     break;
157   case PCDM_SS_DriverFailure:
158     anError = DocError_ResourcesProblem;
159     break;
160   case PCDM_SS_WriteFailure:
161   //case PCDM_SS_DiskWritingFailure:
162   //case PCDM_SS_UserRightsFailure:
163     anError = DocError_CanNotOpen;
164     break;
165   default:
166     anError = DocError_UnknownProblem;
167     break;
168   }
169   return anError;
170 }
171
172 void HYDROData_Document::Close()
173 {
174   myDoc->Close();
175   HYDROData_Application::GetApplication()->RemoveDocument(this);
176 }
177
178 bool HYDROData_Document::DumpToPython( const QString& theFileName,
179                                        const bool     theIsMultiFile ) const
180 {
181   // Try to open the file
182   QFile aFile( theFileName );
183   if ( !aFile.open( QIODevice::WriteOnly ) )
184     return false;
185
186   MapOfTreatedObjects aTreatedObjects;
187
188   // Dump header for python script
189   QStringList aHeaderDump = DumpToPython( aTreatedObjects, theIsMultiFile );
190   if ( aHeaderDump.isEmpty() )
191     return false;
192
193   HYDROData_Tool::WriteStringsToFile( aFile, aHeaderDump );
194
195   bool aRes = true;
196
197   // Dump all model objects to Python script
198   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_IMAGE );
199   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_POLYLINEXY );
200   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_BATHYMETRY );
201   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_PROFILE );
202   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_POLYLINE );
203   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_IMMERSIBLE_ZONE );
204   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_STREAM );
205   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_CHANNEL );
206   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_DIGUE );
207   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_OBSTACLE );
208   aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_CALCULATION );
209
210   // Dump code to close python fuction
211   if ( aRes && theIsMultiFile )
212   {
213     QStringList aFooterScript;
214     aFooterScript << QString( "" );
215     aFooterScript << QString( "  pass" );
216     HYDROData_Tool::WriteStringsToFile( aFile, aFooterScript );
217   }
218
219   return aRes;
220 }
221
222 QString HYDROData_Document::GetDocPyName() const
223 {
224   QString aDocName = PYTHON_DOC_NAME;
225   
226   /*
227   int aDocId = 1;
228   if ( DocumentId( this, aDocId ) )
229     aDocName += "_" + QString::number( aDocId );
230   */
231   
232   return aDocName;
233 }
234
235 QStringList HYDROData_Document::DumpToPython( MapOfTreatedObjects& theTreatedObjects,
236                                               const bool           theIsMultiFile ) const
237 {
238   QString aDocName = GetDocPyName();
239
240   // Append document in to the map of treated objects to prevent names overlaping
241   theTreatedObjects.insert( aDocName, this );
242
243   int aDocId = 1;
244   if ( !DocumentId( this, aDocId ) )
245     aDocId = 1;
246
247   QStringList aResScript;
248
249   aResScript << QString( "from HYDROPy import *" );
250   aResScript << QString( "from PyQt4.QtCore import *" );
251   aResScript << QString( "from PyQt4.QtGui import *" );
252
253   if ( theIsMultiFile )
254   {
255     aResScript << QString( "" );
256     aResScript << QString( "def RebuildData( theStudy ):" );
257     aResScript << QString( "  %1 = HYDROData_Document.Document( theStudy._get_StudyId() );" ).arg( aDocName );
258   }
259   else
260   {
261     aResScript << QString( "" );
262     aResScript << QString( "%1 = HYDROData_Document.Document( theStudy._get_StudyId() );" ).arg( aDocName );
263   }
264
265   return aResScript;
266 }
267
268 bool HYDROData_Document::dumpPartitionToPython( QFile&               theFile,
269                                                 const bool           theIsMultiFile,
270                                                 MapOfTreatedObjects& theTreatedObjects,
271                                                 const ObjectKind&    theObjectKind ) const
272 {
273   if ( !theFile.isOpen() )
274     return false;
275
276   QTextStream anOutStream( &theFile );
277
278   bool aRes = true;
279
280   HYDROData_Iterator anIterator( this, theObjectKind );
281   for( ; anIterator.More(); anIterator.Next() )
282   {
283     Handle(HYDROData_Entity) anObject = anIterator.Current();
284     if ( anObject.IsNull() )
285       continue;
286
287     QString anObjName = anObject->GetName();
288     if ( theTreatedObjects.contains( anObjName ) )
289       continue;
290
291     theTreatedObjects.insert( anObjName, anObject );
292
293     QStringList anObjDump = anObject->DumpToPython( theTreatedObjects );
294
295     if ( theIsMultiFile )
296     {
297       // For multifile dump we use the function, see the document dump header
298       QStringList::iterator anIt = anObjDump.begin();
299       for ( ; anIt != anObjDump.end(); ++anIt )
300         anIt->prepend( "  " );
301     }
302     
303     HYDROData_Tool::WriteStringsToFile( theFile, anObjDump );
304   }
305   
306   return aRes;
307 }
308
309 HYDROData_SequenceOfObjects HYDROData_Document::GetObjectsLayerOrder(
310   const Standard_Boolean theIsAll ) const
311 {
312   HYDROData_SequenceOfObjects anOrder;
313
314   // TODO
315
316   return anOrder;
317 }
318
319 void HYDROData_Document::SetObjectsLayerOrder( const HYDROData_SequenceOfObjects& theOrder )
320 {
321   // TODO
322 }
323
324 void HYDROData_Document::Show( const Handle_HYDROData_Entity& theObject )
325 {
326   // TODO
327 }
328
329 void HYDROData_Document::Show( const HYDROData_SequenceOfObjects& theObjects )
330 {
331   // TODO
332 }
333
334 void HYDROData_Document::StartOperation()
335 {
336   myDoc->NewCommand();
337 }
338
339 void HYDROData_Document::CommitOperation(const TCollection_ExtendedString& theName)
340 {
341   if( !myDoc->CommitCommand() ) // it means that there were no modifications done
342   {
343     myDoc->NewCommand();
344     NewID(); // workaround: do something just to modify the document
345     myDoc->CommitCommand();
346   }
347   myTransactionsAfterSave++;
348
349   if( theName.Length() != 0 )
350   {
351     const TDF_DeltaList& aList = GetUndos();
352     if( !aList.IsEmpty() )
353     {
354       Handle(TDF_Delta) aDelta = aList.Last();
355       if( !aDelta.IsNull() )
356         aDelta->SetName( theName );
357     }
358   }
359 }
360
361 void HYDROData_Document::AbortOperation()
362 {
363   myDoc->AbortCommand();
364 }
365
366 bool HYDROData_Document::IsOperation()
367 {
368   return myDoc->HasOpenCommand() != 0;
369 }
370
371 bool HYDROData_Document::IsModified()
372 {
373   return myTransactionsAfterSave != 0;
374 }
375
376 bool HYDROData_Document::CanUndo()
377 {
378   return myDoc->GetAvailableUndos() > 0;
379 }
380
381 const TDF_DeltaList& HYDROData_Document::GetUndos()
382 {
383   return myDoc->GetUndos();
384 }
385
386 void HYDROData_Document::ClearUndos()
387 {
388   return myDoc->ClearUndos();
389 }
390
391 void HYDROData_Document::Undo()
392 {
393   myDoc->Undo();
394   myTransactionsAfterSave--;
395 }
396
397 bool HYDROData_Document::CanRedo()
398 {
399   return myDoc->GetAvailableRedos() > 0;
400 }
401
402 const TDF_DeltaList& HYDROData_Document::GetRedos()
403 {
404   return myDoc->GetRedos();
405 }
406
407 void HYDROData_Document::ClearRedos()
408 {
409   return myDoc->ClearRedos();
410 }
411
412 void HYDROData_Document::Redo()
413 {
414   myDoc->Redo();
415   myTransactionsAfterSave++;
416 }
417
418 Handle(HYDROData_Entity) HYDROData_Document::CreateObject( const ObjectKind theKind )
419 {
420   return HYDROData_Iterator::CreateObject( this, theKind );
421 }
422
423 Handle(HYDROData_Entity) HYDROData_Document::FindObjectByName( 
424   const QString&   theName,
425   const ObjectKind theObjectKind ) const
426 {
427   Handle(HYDROData_Entity) anObject;
428   if ( theName.isEmpty() )
429     return anObject;
430
431   QStringList aNamesList;
432   aNamesList << theName;
433
434   HYDROData_SequenceOfObjects aSeqOfObjs = FindObjectsByNames( aNamesList, theObjectKind );
435   if( aSeqOfObjs.IsEmpty() )
436     return anObject;
437   
438   anObject = aSeqOfObjs.First();
439   return anObject;
440 }
441
442 HYDROData_SequenceOfObjects HYDROData_Document::FindObjectsByNames(
443   const QStringList& theNames, 
444   const ObjectKind   theObjectKind ) const
445 {
446   HYDROData_SequenceOfObjects aResSeq;
447
448   QStringList aNamesList = theNames;
449
450   HYDROData_Iterator anIter( this, theObjectKind );
451   for( ; anIter.More(); anIter.Next() )
452   {
453     Handle(HYDROData_Entity) anObject = anIter.Current();
454     if( anObject.IsNull() )
455       continue;
456
457     QString anObjName = anObject->GetName();
458     if ( anObjName.isEmpty() || !aNamesList.contains( anObjName ) )
459       continue;
460
461     aResSeq.Append( anObject );
462
463     aNamesList.removeAll( anObjName );
464     if ( aNamesList.isEmpty() )
465       break;
466   }
467
468   return aResSeq;
469 }
470
471 HYDROData_Document::HYDROData_Document()
472 {
473   HYDROData_Application::GetApplication()->NewDocument("BinOcaf", myDoc);
474   myDoc->SetUndoLimit(UNDO_LIMIT);
475   NewID(); // needed to have at least one attribute in initial document to avoid errors
476   myTransactionsAfterSave = 0;
477 }
478
479 HYDROData_Document::HYDROData_Document(const Handle(TDocStd_Document)& theDoc)
480 {
481   myDoc = theDoc;
482   myTransactionsAfterSave = 0;
483 }
484
485 HYDROData_Document::~HYDROData_Document()
486 {
487 }
488
489 int HYDROData_Document::NewID()
490 {
491   TDF_Label anIDLab = myDoc->Main().FindChild(TAG_PROPS).
492     FindChild(TAG_PROPS_NEW_ID);
493   Handle(TDataStd_Integer) anInt;
494   if (!anIDLab.FindAttribute(TDataStd_Integer::GetID(), anInt)) {
495     anInt = TDataStd_Integer::Set(anIDLab, 0);
496   }
497   // just increment value and return
498   anInt->Set(anInt->Get() + 1);
499   return anInt->Get();
500 }
501
502 TDF_Label HYDROData_Document::LabelOfObjects()
503 {
504   return myDoc->Main().FindChild(TAG_OBJECTS);
505 }