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>
9 #include <TDF_Delta.hxx>
12 #include <QStringList>
13 #include <QTextStream>
15 IMPLEMENT_STANDARD_HANDLE(HYDROData_Document,MMgt_TShared)
16 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Document,MMgt_TShared)
18 #define PYTHON_DOC_NAME "hydro_doc"
20 static const int UNDO_LIMIT = 10; // number of possible undo operations in the module
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)
29 typedef QMap<Standard_Integer,Handle_HYDROData_Entity> MapOfOrdered;
30 typedef QMap<QString,Handle_HYDROData_Entity> MapOfUnordered;
32 Handle(HYDROData_Document) HYDROData_Document::Document(const int theStudyID)
34 Handle(HYDROData_Document) aResult =
35 HYDROData_Application::GetApplication()->GetDocument(theStudyID);
36 if (aResult.IsNull()) {
37 aResult = new HYDROData_Document();
38 HYDROData_Application::GetApplication()->AddDocument(theStudyID, aResult);
43 Handle(HYDROData_Document) HYDROData_Document::Document(
44 const TDF_Label& theObjectLabel )
46 Handle(HYDROData_Document) aResDoc;
47 if ( theObjectLabel.IsNull() )
50 Handle(TDocStd_Document) anObjDoc;
53 anObjDoc = TDocStd_Document::Get( theObjectLabel );
59 if ( anObjDoc.IsNull() )
62 HYDROData_Application* anApp = HYDROData_Application::GetApplication();
64 DataMapOfStudyIDDocument::Iterator aMapIt( anApp->myDocuments );
65 for ( ; aMapIt.More(); aMapIt.Next() )
67 Handle(HYDROData_Document) anAppDoc = aMapIt.Value();
68 if ( anAppDoc.IsNull() || anAppDoc->myDoc != anObjDoc )
78 bool HYDROData_Document::HasDocument(const int theStudyID)
80 Handle(HYDROData_Document) aResult =
81 HYDROData_Application::GetApplication()->GetDocument(theStudyID);
82 return !aResult.IsNull();
85 bool HYDROData_Document::DocumentId(const Handle(HYDROData_Document)& theDocument,
88 return HYDROData_Application::GetApplication()->GetDocumentId(theDocument, theDocId);
91 Data_DocError HYDROData_Document::Load(const char* theFileName, const int theStudyID)
93 Handle(TDocStd_Document) aResult;
94 TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
95 PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1;
98 aStatus = HYDROData_Application::GetApplication()->Open (aPath, aResult);
100 catch (Standard_Failure)
102 if (!aResult.IsNull()) {
103 aResult->SetUndoLimit(UNDO_LIMIT);
104 HYDROData_Application::GetApplication()->AddDocument(theStudyID, new HYDROData_Document(aResult));
107 Data_DocError anError;
110 anError = DocError_OK;
112 case PCDM_RS_NoDriver:
113 case PCDM_RS_UnknownFileDriver:
114 case PCDM_RS_NoSchema:
115 case PCDM_RS_DriverFailure:
116 case PCDM_RS_WrongResource:
117 anError = DocError_ResourcesProblem;
119 case PCDM_RS_OpenError:
120 case PCDM_RS_NoDocument:
121 case PCDM_RS_WrongStreamMode:
122 case PCDM_RS_PermissionDenied:
123 anError = DocError_CanNotOpen;
125 case PCDM_RS_NoVersion:
126 anError = DocError_InvalidVersion;
128 case PCDM_RS_ExtensionFailure:
129 case PCDM_RS_FormatFailure:
130 case PCDM_RS_TypeFailure:
131 case PCDM_RS_TypeNotFoundInSchema:
132 case PCDM_RS_UnrecognizedFileFormat:
133 anError = DocError_InvalidFormat;
135 case PCDM_RS_MakeFailure:
137 anError = DocError_UnknownProblem;
143 Data_DocError HYDROData_Document::Save(const char* theFileName)
145 TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
146 PCDM_StoreStatus aStatus;
148 aStatus = HYDROData_Application::GetApplication()->SaveAs (myDoc, aPath);
150 catch (Standard_Failure) {}
151 myTransactionsAfterSave = 0;
152 Standard::Purge(); // Release free memory
155 Data_DocError anError;
158 anError = DocError_OK;
160 case PCDM_SS_DriverFailure:
161 anError = DocError_ResourcesProblem;
163 case PCDM_SS_WriteFailure:
164 //case PCDM_SS_DiskWritingFailure:
165 //case PCDM_SS_UserRightsFailure:
166 anError = DocError_CanNotOpen;
169 anError = DocError_UnknownProblem;
175 void HYDROData_Document::Close()
178 HYDROData_Application::GetApplication()->RemoveDocument(this);
181 bool HYDROData_Document::DumpToPython( const QString& theFileName,
182 const bool theIsMultiFile ) const
184 // Try to open the file
185 QFile aFile( theFileName );
186 if ( !aFile.open( QIODevice::WriteOnly ) )
189 MapOfTreatedObjects aTreatedObjects;
191 // Dump header for python script
192 QStringList aHeaderDump = DumpToPython( aTreatedObjects, theIsMultiFile );
193 if ( aHeaderDump.isEmpty() )
196 HYDROData_Tool::WriteStringsToFile( aFile, aHeaderDump );
200 // Dump all model objects to Python script
201 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_IMAGE );
202 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_POLYLINEXY );
203 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_BATHYMETRY );
204 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_PROFILE );
205 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_POLYLINE );
206 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_IMMERSIBLE_ZONE );
207 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_STREAM );
208 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_CHANNEL );
209 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_DIGUE );
210 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_OBSTACLE );
211 aRes = aRes && dumpPartitionToPython( aFile, theIsMultiFile, aTreatedObjects, KIND_CALCULATION );
213 // Dump code to close python fuction
214 if ( aRes && theIsMultiFile )
216 QStringList aFooterScript;
217 aFooterScript << QString( "" );
218 aFooterScript << QString( " pass" );
219 HYDROData_Tool::WriteStringsToFile( aFile, aFooterScript );
225 QString HYDROData_Document::GetDocPyName() const
227 QString aDocName = PYTHON_DOC_NAME;
231 if ( DocumentId( this, aDocId ) )
232 aDocName += "_" + QString::number( aDocId );
238 QStringList HYDROData_Document::DumpToPython( MapOfTreatedObjects& theTreatedObjects,
239 const bool theIsMultiFile ) const
241 QString aDocName = GetDocPyName();
243 // Append document in to the map of treated objects to prevent names overlaping
244 theTreatedObjects.insert( aDocName, this );
247 if ( !DocumentId( this, aDocId ) )
250 QStringList aResScript;
252 aResScript << QString( "from HYDROPy import *" );
253 aResScript << QString( "from PyQt4.QtCore import *" );
254 aResScript << QString( "from PyQt4.QtGui import *" );
256 if ( theIsMultiFile )
258 aResScript << QString( "" );
259 aResScript << QString( "def RebuildData( theStudy ):" );
260 aResScript << QString( " %1 = HYDROData_Document.Document( theStudy._get_StudyId() );" ).arg( aDocName );
264 aResScript << QString( "" );
265 aResScript << QString( "%1 = HYDROData_Document.Document( theStudy._get_StudyId() );" ).arg( aDocName );
271 bool HYDROData_Document::dumpPartitionToPython( QFile& theFile,
272 const bool theIsMultiFile,
273 MapOfTreatedObjects& theTreatedObjects,
274 const ObjectKind& theObjectKind ) const
276 if ( !theFile.isOpen() )
279 QTextStream anOutStream( &theFile );
283 HYDROData_Iterator anIterator( this, theObjectKind );
284 for( ; anIterator.More(); anIterator.Next() )
286 Handle(HYDROData_Entity) anObject = anIterator.Current();
287 if ( anObject.IsNull() )
290 QString anObjName = anObject->GetName();
291 if ( theTreatedObjects.contains( anObjName ) )
294 theTreatedObjects.insert( anObjName, anObject );
296 QStringList anObjDump = anObject->DumpToPython( theTreatedObjects );
298 if ( theIsMultiFile )
300 // For multifile dump we use the function, see the document dump header
301 QStringList::iterator anIt = anObjDump.begin();
302 for ( ; anIt != anObjDump.end(); ++anIt )
303 anIt->prepend( " " );
306 HYDROData_Tool::WriteStringsToFile( theFile, anObjDump );
312 bool takeLastDigits( QString& theStr, int& aRes )
317 for ( int i = theStr.length() - 1; i >= 0; --i )
319 const QChar& aChar = theStr.at( i );
320 if ( !aChar.isDigit() )
323 anStrNum.prepend( aChar );
326 if ( anStrNum.isEmpty() )
329 theStr.remove( theStr.length() - anStrNum.length(), anStrNum.length() );
330 aRes = anStrNum.toInt();
335 bool isObjectNameLessThan( const QString& theStr1, const QString& theStr2 )
337 QString aStr1 = theStr1, aStr2 = theStr2;
339 int aNum1 = -1, aNum2 = -1;
340 if ( takeLastDigits( aStr1, aNum1 ) && takeLastDigits( aStr2, aNum2 ) )
342 if ( aStr1 == aStr2 )
343 return aNum1 < aNum2;
346 return theStr1 < theStr2;
349 HYDROData_SequenceOfObjects HYDROData_Document::GetObjectsLayerOrder(
350 const Standard_Boolean theIsAll ) const
352 HYDROData_SequenceOfObjects anOrder;
354 MapOfOrdered aMapOfOrdered;
355 MapOfUnordered aMapOfUnordered;
357 HYDROData_Iterator anIter( this );
358 for ( ; anIter.More(); anIter.Next() )
360 Handle(HYDROData_Entity) anObject = anIter.Current();
361 if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
364 Standard_Integer anObjZLevel = -1;
365 if ( anObject->GetZLevel( anObjZLevel ) )
367 aMapOfOrdered.insert( anObjZLevel, anObject );
371 QString anObjName = anObject->GetName();
372 if ( anObjName.isEmpty() )
375 aMapOfUnordered.insert( anObjName, anObject );
379 MapOfOrdered::const_iterator anOrderedMapIt = aMapOfOrdered.constBegin();
380 for ( ; anOrderedMapIt != aMapOfOrdered.constEnd(); anOrderedMapIt++ )
382 const Handle(HYDROData_Entity)& anObject = anOrderedMapIt.value();
383 anOrder.Prepend( anObject );
388 QStringList aSortedNames = aMapOfUnordered.keys();
389 qSort( aSortedNames.begin(), aSortedNames.end(), isObjectNameLessThan );
391 for ( int i = 0; i < aSortedNames.length(); ++i )
393 QString anObjName = aSortedNames.value( i );
395 const Handle(HYDROData_Entity)& anObject = aMapOfUnordered.value( anObjName );
396 anOrder.Append( anObject );
403 void HYDROData_Document::SetObjectsLayerOrder( const HYDROData_SequenceOfObjects& theOrder )
405 // At first we remove previous model order
406 RemoveObjectsLayerOrder();
408 // Make new objects order
409 Standard_Integer aLevel = 0;
410 for ( int i = theOrder.Length(), n = 1; i >= n; --i )
412 const Handle(HYDROData_Entity)& anObject = theOrder.Value( i );
413 if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
416 anObject->SetZLevel( aLevel++ );
420 void HYDROData_Document::Show( const Handle_HYDROData_Entity& theObject )
422 HYDROData_SequenceOfObjects anOrder;
423 anOrder.Append( theObject );
427 void HYDROData_Document::Show( const HYDROData_SequenceOfObjects& theObjects )
429 MapOfUnordered aMapOfUnordered;
431 for ( int i = 1, n = theObjects.Length(); i <= n; ++i )
433 const Handle(HYDROData_Entity)& anObject = theObjects.Value( i );
434 if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
437 Standard_Integer anObjZLevel = -1;
438 if ( anObject->GetZLevel( anObjZLevel ) )
440 continue; // Skip objects that already have the z-level
444 QString anObjName = anObject->GetName();
445 if ( anObjName.isEmpty() )
448 aMapOfUnordered.insert( anObjName, anObject );
452 if ( aMapOfUnordered.isEmpty() )
453 return; // Nothing to show
455 Standard_Integer aTopId = 0;
457 HYDROData_SequenceOfObjects aModelOrder = GetObjectsLayerOrder( Standard_False );
458 if ( !aModelOrder.IsEmpty() )
460 const Handle(HYDROData_Entity)& anObject = aModelOrder.First();
461 anObject->GetZLevel( aTopId );
465 aTopId += aMapOfUnordered.size() - 1;
467 QStringList aSortedNames = aMapOfUnordered.keys();
468 qSort( aSortedNames.begin(), aSortedNames.end(), isObjectNameLessThan );
470 for ( int i = 0; i < aSortedNames.length(); ++i )
472 QString anObjName = aSortedNames.value( i );
474 const Handle(HYDROData_Entity)& anObject = aMapOfUnordered.value( anObjName );
475 anObject->SetZLevel( aTopId-- );
479 void HYDROData_Document::RemoveObjectsLayerOrder()
481 HYDROData_Iterator anIter( this );
482 for ( ; anIter.More(); anIter.Next() )
484 Handle(HYDROData_Entity) anObject = anIter.Current();
485 if ( anObject.IsNull() || !anObject->IsHas2dPrs() )
488 anObject->RemoveZLevel();
492 void HYDROData_Document::StartOperation()
497 void HYDROData_Document::CommitOperation(const TCollection_ExtendedString& theName)
499 if( !myDoc->CommitCommand() ) // it means that there were no modifications done
502 NewID(); // workaround: do something just to modify the document
503 myDoc->CommitCommand();
505 myTransactionsAfterSave++;
507 if( theName.Length() != 0 )
509 const TDF_DeltaList& aList = GetUndos();
510 if( !aList.IsEmpty() )
512 Handle(TDF_Delta) aDelta = aList.Last();
513 if( !aDelta.IsNull() )
514 aDelta->SetName( theName );
519 void HYDROData_Document::AbortOperation()
521 myDoc->AbortCommand();
524 bool HYDROData_Document::IsOperation()
526 return myDoc->HasOpenCommand() != 0;
529 bool HYDROData_Document::IsModified()
531 return myTransactionsAfterSave != 0;
534 bool HYDROData_Document::CanUndo()
536 return myDoc->GetAvailableUndos() > 0;
539 const TDF_DeltaList& HYDROData_Document::GetUndos()
541 return myDoc->GetUndos();
544 void HYDROData_Document::ClearUndos()
546 return myDoc->ClearUndos();
549 void HYDROData_Document::Undo()
552 myTransactionsAfterSave--;
555 bool HYDROData_Document::CanRedo()
557 return myDoc->GetAvailableRedos() > 0;
560 const TDF_DeltaList& HYDROData_Document::GetRedos()
562 return myDoc->GetRedos();
565 void HYDROData_Document::ClearRedos()
567 return myDoc->ClearRedos();
570 void HYDROData_Document::Redo()
573 myTransactionsAfterSave++;
576 Handle(HYDROData_Entity) HYDROData_Document::CreateObject( const ObjectKind theKind )
578 return HYDROData_Iterator::CreateObject( this, theKind );
581 Handle(HYDROData_Entity) HYDROData_Document::FindObjectByName(
582 const QString& theName,
583 const ObjectKind theObjectKind ) const
585 Handle(HYDROData_Entity) anObject;
586 if ( theName.isEmpty() )
589 QStringList aNamesList;
590 aNamesList << theName;
592 HYDROData_SequenceOfObjects aSeqOfObjs = FindObjectsByNames( aNamesList, theObjectKind );
593 if( aSeqOfObjs.IsEmpty() )
596 anObject = aSeqOfObjs.First();
600 HYDROData_SequenceOfObjects HYDROData_Document::FindObjectsByNames(
601 const QStringList& theNames,
602 const ObjectKind theObjectKind ) const
604 HYDROData_SequenceOfObjects aResSeq;
606 QStringList aNamesList = theNames;
608 HYDROData_Iterator anIter( this, theObjectKind );
609 for( ; anIter.More(); anIter.Next() )
611 Handle(HYDROData_Entity) anObject = anIter.Current();
612 if( anObject.IsNull() )
615 QString anObjName = anObject->GetName();
616 if ( anObjName.isEmpty() || !aNamesList.contains( anObjName ) )
619 aResSeq.Append( anObject );
621 aNamesList.removeAll( anObjName );
622 if ( aNamesList.isEmpty() )
629 HYDROData_Document::HYDROData_Document()
631 HYDROData_Application::GetApplication()->NewDocument("BinOcaf", myDoc);
632 myDoc->SetUndoLimit(UNDO_LIMIT);
633 NewID(); // needed to have at least one attribute in initial document to avoid errors
634 myTransactionsAfterSave = 0;
637 HYDROData_Document::HYDROData_Document(const Handle(TDocStd_Document)& theDoc)
640 myTransactionsAfterSave = 0;
643 HYDROData_Document::~HYDROData_Document()
647 int HYDROData_Document::NewID()
649 TDF_Label anIDLab = myDoc->Main().FindChild(TAG_PROPS).
650 FindChild(TAG_PROPS_NEW_ID);
651 Handle(TDataStd_Integer) anInt;
652 if (!anIDLab.FindAttribute(TDataStd_Integer::GetID(), anInt)) {
653 anInt = TDataStd_Integer::Set(anIDLab, 0);
655 // just increment value and return
656 anInt->Set(anInt->Get() + 1);
660 TDF_Label HYDROData_Document::LabelOfObjects()
662 return myDoc->Main().FindChild(TAG_OBJECTS);