2 #include <HYDROData_Document.h>
3 #include <HYDROData_Application.h>
4 #include <HYDROData_Iterator.h>
5 #include <HYDROData_Tool.h>
7 #include <TDataStd_Integer.hxx>
8 #include <TDataXtd_Position.hxx>
10 #include <TDF_Delta.hxx>
12 #include <gp_Pnt2d.hxx>
16 #include <QStringList>
17 #include <QTextStream>
19 IMPLEMENT_STANDARD_HANDLE(HYDROData_Document,MMgt_TShared)
20 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Document,MMgt_TShared)
22 #define PYTHON_DOC_NAME "hydro_doc"
24 static const int UNDO_LIMIT = 10; // number of possible undo operations in the module
26 static const int TAG_PROPS = 1; // general properties tag
27 static const int TAG_PROPS_NEW_ID = 1; // general properties: tag for storage of the new object ID
28 static const int TAG_OBJECTS = 2; // tag of the objects sub-tree
29 static const int TAG_HISTORY = 3; // tag of the history sub-tree (Root for History)
30 static const int TAG_LOCAL_CS = 4; // tag of local coordinate system information
31 static const gp_Pnt2d DEFAULT_LOCAL_CS( 0, 0 );
35 typedef QMap<Standard_Integer,Handle_HYDROData_Entity> MapOfOrdered;
36 typedef QMap<QString,Handle_HYDROData_Entity> MapOfUnordered;
38 Handle(HYDROData_Document) HYDROData_Document::Document(const int theStudyID)
40 Handle(HYDROData_Document) aResult =
41 HYDROData_Application::GetApplication()->GetDocument(theStudyID);
42 if (aResult.IsNull()) {
43 aResult = new HYDROData_Document();
44 HYDROData_Application::GetApplication()->AddDocument(theStudyID, aResult);
49 Handle(HYDROData_Document) HYDROData_Document::Document(
50 const TDF_Label& theObjectLabel )
52 Handle(HYDROData_Document) aResDoc;
53 if ( theObjectLabel.IsNull() )
56 Handle(TDocStd_Document) anObjDoc;
59 anObjDoc = TDocStd_Document::Get( theObjectLabel );
65 if ( anObjDoc.IsNull() )
68 HYDROData_Application* anApp = HYDROData_Application::GetApplication();
70 DataMapOfStudyIDDocument::Iterator aMapIt( anApp->myDocuments );
71 for ( ; aMapIt.More(); aMapIt.Next() )
73 Handle(HYDROData_Document) anAppDoc = aMapIt.Value();
74 if ( anAppDoc.IsNull() || anAppDoc->myDoc != anObjDoc )
84 bool HYDROData_Document::HasDocument(const int theStudyID)
86 Handle(HYDROData_Document) aResult =
87 HYDROData_Application::GetApplication()->GetDocument(theStudyID);
88 return !aResult.IsNull();
91 bool HYDROData_Document::DocumentId(const Handle(HYDROData_Document)& theDocument,
94 return HYDROData_Application::GetApplication()->GetDocumentId(theDocument, theDocId);
97 Data_DocError HYDROData_Document::Load(const char* theFileName, const int theStudyID)
99 Handle(TDocStd_Document) aResult;
100 TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
101 PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1;
104 aStatus = HYDROData_Application::GetApplication()->Open (aPath, aResult);
106 catch (Standard_Failure)
108 if (!aResult.IsNull()) {
109 aResult->SetUndoLimit(UNDO_LIMIT);
110 HYDROData_Application::GetApplication()->AddDocument(theStudyID, new HYDROData_Document(aResult));
113 Data_DocError anError;
116 anError = DocError_OK;
118 case PCDM_RS_NoDriver:
119 case PCDM_RS_UnknownFileDriver:
120 case PCDM_RS_NoSchema:
121 case PCDM_RS_DriverFailure:
122 case PCDM_RS_WrongResource:
123 anError = DocError_ResourcesProblem;
125 case PCDM_RS_OpenError:
126 case PCDM_RS_NoDocument:
127 case PCDM_RS_WrongStreamMode:
128 case PCDM_RS_PermissionDenied:
129 anError = DocError_CanNotOpen;
131 case PCDM_RS_NoVersion:
132 anError = DocError_InvalidVersion;
134 case PCDM_RS_ExtensionFailure:
135 case PCDM_RS_FormatFailure:
136 case PCDM_RS_TypeFailure:
137 case PCDM_RS_TypeNotFoundInSchema:
138 case PCDM_RS_UnrecognizedFileFormat:
139 anError = DocError_InvalidFormat;
141 case PCDM_RS_MakeFailure:
143 anError = DocError_UnknownProblem;
149 Data_DocError HYDROData_Document::Save(const char* theFileName)
151 TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
152 PCDM_StoreStatus aStatus;
154 aStatus = HYDROData_Application::GetApplication()->SaveAs (myDoc, aPath);
156 catch (Standard_Failure) {}
157 myTransactionsAfterSave = 0;
158 Standard::Purge(); // Release free memory
161 Data_DocError anError;
164 anError = DocError_OK;
166 case PCDM_SS_DriverFailure:
167 anError = DocError_ResourcesProblem;
169 case PCDM_SS_WriteFailure:
170 //case PCDM_SS_DiskWritingFailure:
171 //case PCDM_SS_UserRightsFailure:
172 anError = DocError_CanNotOpen;
175 anError = DocError_UnknownProblem;
181 void HYDROData_Document::Close()
184 HYDROData_Application::GetApplication()->RemoveDocument(this);
187 bool HYDROData_Document::DumpToPython( const QString& theFileName,
188 const bool theIsMultiFile ) const
190 // Try to open the file
191 QFile aFile( theFileName );
192 if ( !aFile.open( QIODevice::WriteOnly ) )
195 MapOfTreatedObjects aTreatedObjects;
197 // Dump header for python script
198 QStringList aHeaderDump = DumpToPython( aTreatedObjects, theIsMultiFile );
199 if ( aHeaderDump.isEmpty() )
202 HYDROData_Tool::WriteStringsToFile( aFile, aHeaderDump );
206 // Dump all model objects to Python script
207 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_IMAGE );
208 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_POLYLINEXY );
209 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_BATHYMETRY );
210 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_PROFILE );
211 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_POLYLINE );
212 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_IMMERSIBLE_ZONE );
213 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_STREAM );
214 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_CHANNEL );
215 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_DIGUE );
216 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_OBSTACLE );
217 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_CALCULATION );
219 // Dump code to close python fuction
220 if ( aRes && theIsMultiFile )
222 QStringList aFooterScript;
223 aFooterScript << QString( "" );
224 aFooterScript << QString( " pass" );
225 HYDROData_Tool::WriteStringsToFile( aFile, aFooterScript );
231 QString HYDROData_Document::GetDocPyName() const
233 QString aDocName = PYTHON_DOC_NAME;
237 if ( DocumentId( this, aDocId ) )
238 aDocName += "_" + QString::number( aDocId );
244 QStringList HYDROData_Document::DumpToPython( MapOfTreatedObjects& theTreatedObjects,
245 const bool theIsMultiFile ) const
247 QString aDocName = GetDocPyName();
249 // Append document in to the map of treated objects to prevent names overlaping
250 theTreatedObjects.insert( aDocName, this );
253 if ( !DocumentId( this, aDocId ) )
256 QStringList aResScript;
258 aResScript << QString( "from HYDROPy import *" );
259 aResScript << QString( "from PyQt4.QtCore import *" );
260 aResScript << QString( "from PyQt4.QtGui import *" );
262 if ( theIsMultiFile )
264 aResScript << QString( "" );
265 aResScript << QString( "def RebuildData( theStudy ):" );
266 aResScript << QString( " %1 = HYDROData_Document.Document( theStudy._get_StudyId() );" ).arg( aDocName );
270 aResScript << QString( "" );
271 aResScript << QString( "%1 = HYDROData_Document.Document( theStudy._get_StudyId() );" ).arg( aDocName );
277 bool HYDROData_Document::dumpPartitionToPython( QFile& theFile,
278 const bool theIsMultiFile,
279 MapOfTreatedObjects& theTreatedObjects,
280 const ObjectKind& theObjectKind ) const
282 if ( !theFile.isOpen() )
285 QTextStream anOutStream( &theFile );
289 HYDROData_Iterator anIterator( this, theObjectKind );
290 for( ; anIterator.More(); anIterator.Next() )
292 Handle(HYDROData_Entity) anObject = anIterator.Current();
293 if ( anObject.IsNull() )
296 QString anObjName = anObject->GetName();
297 if ( theTreatedObjects.contains( anObjName ) )
300 theTreatedObjects.insert( anObjName, anObject );
302 QStringList anObjDump = anObject->DumpToPython( theTreatedObjects );
304 if ( theIsMultiFile )
306 // For multifile dump we use the function, see the document dump header
307 QStringList::iterator anIt = anObjDump.begin();
308 for ( ; anIt != anObjDump.end(); ++anIt )
309 anIt->prepend( " " );
312 HYDROData_Tool::WriteStringsToFile( theFile, anObjDump );
318 bool takeLastDigits( QString& theStr, int& aRes )
323 for ( int i = theStr.length() - 1; i >= 0; --i )
325 const QChar& aChar = theStr.at( i );
326 if ( !aChar.isDigit() )
329 anStrNum.prepend( aChar );
332 if ( anStrNum.isEmpty() )
335 theStr.remove( theStr.length() - anStrNum.length(), anStrNum.length() );
336 aRes = anStrNum.toInt();
341 bool isObjectNameLessThan( const QString& theStr1, const QString& theStr2 )
343 QString aStr1 = theStr1, aStr2 = theStr2;
345 int aNum1 = -1, aNum2 = -1;
346 if ( takeLastDigits( aStr1, aNum1 ) && takeLastDigits( aStr2, aNum2 ) )
348 if ( aStr1 == aStr2 )
349 return aNum1 < aNum2;
352 return theStr1 < theStr2;
355 HYDROData_SequenceOfObjects HYDROData_Document::GetObjectsLayerOrder(
356 const Standard_Boolean theIsAll ) const
358 HYDROData_SequenceOfObjects anOrder;
360 MapOfOrdered aMapOfOrdered;
361 MapOfUnordered aMapOfUnordered;
363 HYDROData_Iterator anIter( this );
364 for ( ; anIter.More(); anIter.Next() )
366 Handle(HYDROData_Entity) anObject = anIter.Current();
367 if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
370 Standard_Integer anObjZLevel = -1;
371 if ( anObject->GetZLevel( anObjZLevel ) )
373 aMapOfOrdered.insert( anObjZLevel, anObject );
377 QString anObjName = anObject->GetName();
378 if ( anObjName.isEmpty() )
381 aMapOfUnordered.insert( anObjName, anObject );
385 MapOfOrdered::const_iterator anOrderedMapIt = aMapOfOrdered.constBegin();
386 for ( ; anOrderedMapIt != aMapOfOrdered.constEnd(); anOrderedMapIt++ )
388 const Handle(HYDROData_Entity)& anObject = anOrderedMapIt.value();
389 anOrder.Prepend( anObject );
394 QStringList aSortedNames = aMapOfUnordered.keys();
395 qSort( aSortedNames.begin(), aSortedNames.end(), isObjectNameLessThan );
397 for ( int i = 0; i < aSortedNames.length(); ++i )
399 QString anObjName = aSortedNames.value( i );
401 const Handle(HYDROData_Entity)& anObject = aMapOfUnordered.value( anObjName );
402 anOrder.Append( anObject );
409 void HYDROData_Document::SetObjectsLayerOrder( const HYDROData_SequenceOfObjects& theOrder )
411 // At first we remove previous model order
412 RemoveObjectsLayerOrder();
414 // Make new objects order
415 Standard_Integer aLevel = 0;
416 for ( int i = theOrder.Length(), n = 1; i >= n; --i )
418 const Handle(HYDROData_Entity)& anObject = theOrder.Value( i );
419 if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
422 anObject->SetZLevel( aLevel++ );
426 void HYDROData_Document::Show( const Handle_HYDROData_Entity& theObject )
428 HYDROData_SequenceOfObjects anOrder;
429 anOrder.Append( theObject );
433 void HYDROData_Document::Show( const HYDROData_SequenceOfObjects& theObjects )
435 MapOfUnordered aMapOfUnordered;
437 for ( int i = 1, n = theObjects.Length(); i <= n; ++i )
439 const Handle(HYDROData_Entity)& anObject = theObjects.Value( i );
440 if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
443 Standard_Integer anObjZLevel = -1;
444 if ( anObject->GetZLevel( anObjZLevel ) )
446 continue; // Skip objects that already have the z-level
450 QString anObjName = anObject->GetName();
451 if ( anObjName.isEmpty() )
454 aMapOfUnordered.insert( anObjName, anObject );
458 if ( aMapOfUnordered.isEmpty() )
459 return; // Nothing to show
461 Standard_Integer aTopId = 0;
463 HYDROData_SequenceOfObjects aModelOrder = GetObjectsLayerOrder( Standard_False );
464 if ( !aModelOrder.IsEmpty() )
466 const Handle(HYDROData_Entity)& anObject = aModelOrder.First();
467 anObject->GetZLevel( aTopId );
471 aTopId += aMapOfUnordered.size() - 1;
473 QStringList aSortedNames = aMapOfUnordered.keys();
474 qSort( aSortedNames.begin(), aSortedNames.end(), isObjectNameLessThan );
476 for ( int i = 0; i < aSortedNames.length(); ++i )
478 QString anObjName = aSortedNames.value( i );
480 const Handle(HYDROData_Entity)& anObject = aMapOfUnordered.value( anObjName );
481 anObject->SetZLevel( aTopId-- );
485 void HYDROData_Document::RemoveObjectsLayerOrder()
487 HYDROData_Iterator anIter( this );
488 for ( ; anIter.More(); anIter.Next() )
490 Handle(HYDROData_Entity) anObject = anIter.Current();
491 if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
494 anObject->RemoveZLevel();
498 void HYDROData_Document::StartOperation()
503 void HYDROData_Document::CommitOperation(const TCollection_ExtendedString& theName)
505 if( !myDoc->CommitCommand() ) // it means that there were no modifications done
508 NewID(); // workaround: do something just to modify the document
509 myDoc->CommitCommand();
511 myTransactionsAfterSave++;
513 if( theName.Length() != 0 )
515 const TDF_DeltaList& aList = GetUndos();
516 if( !aList.IsEmpty() )
518 Handle(TDF_Delta) aDelta = aList.Last();
519 if( !aDelta.IsNull() )
520 aDelta->SetName( theName );
525 void HYDROData_Document::AbortOperation()
527 myDoc->AbortCommand();
530 bool HYDROData_Document::IsOperation()
532 return myDoc->HasOpenCommand() != 0;
535 bool HYDROData_Document::IsModified()
537 return myTransactionsAfterSave != 0;
540 bool HYDROData_Document::CanUndo()
542 return myDoc->GetAvailableUndos() > 0;
545 const TDF_DeltaList& HYDROData_Document::GetUndos()
547 return myDoc->GetUndos();
550 void HYDROData_Document::ClearUndos()
552 return myDoc->ClearUndos();
555 void HYDROData_Document::Undo()
558 myTransactionsAfterSave--;
561 bool HYDROData_Document::CanRedo()
563 return myDoc->GetAvailableRedos() > 0;
566 const TDF_DeltaList& HYDROData_Document::GetRedos()
568 return myDoc->GetRedos();
571 void HYDROData_Document::ClearRedos()
573 return myDoc->ClearRedos();
576 void HYDROData_Document::Redo()
579 myTransactionsAfterSave++;
582 Handle(HYDROData_Entity) HYDROData_Document::CreateObject( const ObjectKind theKind )
584 return HYDROData_Iterator::CreateObject( this, theKind );
587 Handle(HYDROData_Entity) HYDROData_Document::FindObjectByName(
588 const QString& theName,
589 const ObjectKind theObjectKind ) const
591 Handle(HYDROData_Entity) anObject;
592 if ( theName.isEmpty() )
595 QStringList aNamesList;
596 aNamesList << theName;
598 HYDROData_SequenceOfObjects aSeqOfObjs = FindObjectsByNames( aNamesList, theObjectKind );
599 if( aSeqOfObjs.IsEmpty() )
602 anObject = aSeqOfObjs.First();
606 HYDROData_SequenceOfObjects HYDROData_Document::FindObjectsByNames(
607 const QStringList& theNames,
608 const ObjectKind theObjectKind ) const
610 HYDROData_SequenceOfObjects aResSeq;
612 QStringList aNamesList = theNames;
614 HYDROData_Iterator anIter( this, theObjectKind );
615 for( ; anIter.More(); anIter.Next() )
617 Handle(HYDROData_Entity) anObject = anIter.Current();
618 if( anObject.IsNull() )
621 QString anObjName = anObject->GetName();
622 if ( anObjName.isEmpty() || !aNamesList.contains( anObjName ) )
625 aResSeq.Append( anObject );
627 aNamesList.removeAll( anObjName );
628 if ( aNamesList.isEmpty() )
635 HYDROData_Document::HYDROData_Document()
637 HYDROData_Application::GetApplication()->NewDocument("BinOcaf", myDoc);
638 myDoc->SetUndoLimit(UNDO_LIMIT);
639 NewID(); // needed to have at least one attribute in initial document to avoid errors
640 myTransactionsAfterSave = 0;
643 HYDROData_Document::HYDROData_Document(const Handle(TDocStd_Document)& theDoc)
646 myTransactionsAfterSave = 0;
649 HYDROData_Document::~HYDROData_Document()
653 int HYDROData_Document::NewID()
655 TDF_Label anIDLab = myDoc->Main().FindChild(TAG_PROPS).
656 FindChild(TAG_PROPS_NEW_ID);
657 Handle(TDataStd_Integer) anInt;
658 if (!anIDLab.FindAttribute(TDataStd_Integer::GetID(), anInt)) {
659 anInt = TDataStd_Integer::Set(anIDLab, 0);
661 // just increment value and return
662 anInt->Set(anInt->Get() + 1);
666 TDF_Label HYDROData_Document::LabelOfObjects()
668 return myDoc->Main().FindChild(TAG_OBJECTS);
671 TDF_Label HYDROData_Document::LabelOfLocalCS() const
673 return myDoc->Main().FindChild(TAG_LOCAL_CS);
676 gp_Pnt2d HYDROData_Document::GetLocalCS() const
678 TDF_Label aLocalCSLab = LabelOfLocalCS();
680 Handle( TDataXtd_Position ) aLocalCS;
681 if( aLocalCSLab.FindAttribute( TDataXtd_Position::GetID(), aLocalCS ) )
683 gp_Pnt aLocalCS3d = aLocalCS->GetPosition();
684 return gp_Pnt2d( aLocalCS3d.X(), aLocalCS3d.Y() );
687 return DEFAULT_LOCAL_CS;
690 void HYDROData_Document::SetLocalCS( const gp_Pnt2d& theLocalCS )
692 TDF_Label aLocalCSLab = LabelOfLocalCS();
694 Handle( TDataXtd_Position ) aLocalCS;
695 if( !aLocalCSLab.FindAttribute( TDataXtd_Position::GetID(), aLocalCS ) )
696 aLocalCS = TDataXtd_Position::Set( aLocalCSLab );
698 gp_Pnt aLocalCS3d( theLocalCS.X(), theLocalCS.Y(), 0 );
699 aLocalCS->SetPosition( aLocalCS3d );