Salome HOME
e946262885d0f9613579ec6ed617f0e4c545c507
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_DataModel.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "HYDROGUI_DataModel.h"
24
25 #include "HYDROGUI_DataObject.h"
26 #include "HYDROGUI_Module.h"
27 #include "HYDROGUI_Tool.h"
28
29 #include <HYDROData_Bathymetry.h>
30 #include <HYDROData_Calculation.h>
31 #include <HYDROData_Document.h>
32 #include <HYDROData_Image.h>
33 #include <HYDROData_Iterator.h>
34 #include <HYDROData_Polyline.h>
35 #include <HYDROData_VisualState.h>
36
37 #include <CAM_Application.h>
38 #include <CAM_DataObject.h>
39 #include <CAM_Module.h>
40 #include <CAM_Study.h>
41
42 #include <LightApp_Application.h>
43 #include <LightApp_DataObject.h>
44 #include <LightApp_Study.h>
45
46 #include <SUIT_DataObject.h>
47 #include <SUIT_DataBrowser.h>
48 #include <SUIT_ResourceMgr.h>
49 #include <SUIT_Study.h>
50 #include <SUIT_Tools.h>
51
52 #include <HYDROData_Document.h>
53
54 #include <TDF_Delta.hxx>
55 #include <TDF_ListIteratorOfDeltaList.hxx>
56
57 #include <QApplication>
58 #include <QDir>
59
60 static HYDROData_SequenceOfObjects myCopyingObjects;
61
62 HYDROGUI_DataModel::HYDROGUI_DataModel( CAM_Module* theModule )
63 : LightApp_DataModel( theModule )
64 {
65   update( module()->application()->activeStudy()->id() );
66 }
67
68 HYDROGUI_DataModel::~HYDROGUI_DataModel()
69 {
70 }
71
72 bool HYDROGUI_DataModel::open( const QString& theURL,
73                                CAM_Study* theStudy,
74                                QStringList theFileList )
75 {
76   LightApp_DataModel::open( theURL, theStudy, theFileList );
77   const int aStudyId = theStudy->id();
78
79   Data_DocError res = DocError_UnknownProblem;
80   if( theFileList.count() == 2 )
81   {
82     QString aTmpDir = theFileList[0];
83     QString aFileName = theFileList[1];
84
85     myStudyURL = theURL;
86     QString aFullPath = SUIT_Tools::addSlash( aTmpDir ) + aFileName;
87
88     try
89     {
90       res = HYDROData_Document::Load( (char*)aFullPath.toLatin1().constData(), aStudyId );
91     }
92     catch(...)
93     {
94       res = DocError_UnknownProblem;
95     }
96     if( res != DocError_OK )
97     {
98       module()->application()->putInfo( tr( "LOAD_ERROR" ) );
99       return false;
100     }
101   }
102
103   // if the document open was successful, the data model update happens
104   // in the set mode of the module
105   if( res == DocError_OK )
106     update( aStudyId );
107
108   return true;
109 }
110
111 bool HYDROGUI_DataModel::save( QStringList& theFileList )
112 {
113   if( !module()->application()->activeStudy() )
114     return false;
115   
116   LightApp_DataModel::save( theFileList );
117
118   QString aTmpDir;
119   QString aFileName;
120   SUIT_ResourceMgr* resMgr = module()->application()->resourceMgr();
121   bool isMultiFile = false;
122   if( resMgr )
123     isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
124
125   // save data to temporary files
126   LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( module()->application()->activeStudy() );
127   aTmpDir = aStudy->GetTmpDir( myStudyURL.toLatin1().constData(), isMultiFile ).c_str();
128   aFileName = SUIT_Tools::file( myStudyURL, false ) + "_HYDRO.cbf";
129
130   QString aFullPath = aTmpDir + aFileName;
131   Data_DocError res = getDocument()->Save( (char*)aFullPath.toLatin1().constData() );
132   if( res != DocError_OK )
133   {
134     module()->application()->putInfo( tr( "SAVE_ERROR" ) );
135     return false;
136   }
137
138   theFileList.append( aTmpDir );
139   theFileList.append( aFileName );
140
141   return true;
142 }
143
144 bool HYDROGUI_DataModel::saveAs( const QString& theURL,
145                                  CAM_Study*,
146                                  QStringList& theFileList )
147 {
148   myStudyURL = theURL;
149   return save( theFileList );
150 }
151
152 bool HYDROGUI_DataModel::close()
153 {
154   return true;
155 }
156
157 bool HYDROGUI_DataModel::dumpPython( const QString& theURL,
158                                      CAM_Study*     theStudy,
159                                      bool           isMultiFile,
160                                      QStringList&   theListOfFiles )
161 {
162   LightApp_DataModel::dumpPython( theURL, theStudy, isMultiFile, theListOfFiles );
163
164   int aStudyId = theStudy->id();
165
166   LightApp_Study* aStudy = ::qobject_cast<LightApp_Study*>( theStudy );
167   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( aStudyId );
168   if ( aDocument.IsNull() || !aStudy )
169     return false;
170
171   QString aFileToExport = aStudy->GetTmpDir( theURL.toLatin1().constData(), isMultiFile ).c_str();
172   aFileToExport += QString( QDir::separator() ) + "HYDRO.py";
173
174   bool aRes = aDocument->DumpToPython( aFileToExport );
175
176   if ( aRes )
177   {
178     theListOfFiles.append( aFileToExport );
179   }
180
181   return aRes;
182 }
183
184 bool HYDROGUI_DataModel::isModified() const
185 {
186   return getDocument()->IsModified();
187 }
188
189 bool HYDROGUI_DataModel::isSaved() const
190 {
191   return true;
192 }
193
194 void HYDROGUI_DataModel::update( const int theStudyId )
195 {
196   LightApp_Application* anApp = dynamic_cast<LightApp_Application*>( module()->application() );
197   if( !anApp )
198     return;
199
200   SUIT_DataObject* aStudyRoot = anApp->activeStudy()->root();
201   if( !aStudyRoot )
202     return;
203
204   // create root object if not exist
205   CAM_DataObject* aRootObj = root();
206   if( !aRootObj )
207     aRootObj = createRootModuleObject( aStudyRoot );
208
209   if( !aRootObj )
210     return;
211
212   DataObjectList aList;
213   aRootObj->children( aList );
214   QListIterator<SUIT_DataObject*> anIter( aList );
215   while( anIter.hasNext() )
216     removeChild( aRootObj, anIter.next() );
217
218   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( theStudyId );
219   if( aDocument.IsNull() )
220     return;
221
222   LightApp_DataObject* anImageRootObj = createObject( aRootObj, "IMAGES" );
223
224   HYDROData_Iterator anIterator( aDocument, KIND_IMAGE );
225   for( ; anIterator.More(); anIterator.Next() )
226   {
227     Handle(HYDROData_Image) anImageObj =
228       Handle(HYDROData_Image)::DownCast( anIterator.Current() );
229     if( !anImageObj.IsNull() )
230     {
231       if( LightApp_DataObject* anImageDataObj = createObject( anImageRootObj, anImageObj ) )
232       {
233         for( int anIndex = 0, aNbRef = anImageObj->NbReferences(); anIndex < aNbRef; anIndex++ )
234         {
235           Handle(HYDROData_Object) aRefObj = anImageObj->Reference( anIndex );
236           if( !aRefObj.IsNull() && !aRefObj->IsRemoved() )
237             createObject( anImageDataObj, aRefObj, anImageDataObj->entry() );
238         }
239       }
240     }
241   }
242
243   LightApp_DataObject* aBathymetryRootObj = createObject( aRootObj, "BATHYMETRIES" );
244
245   anIterator = HYDROData_Iterator( aDocument, KIND_BATHYMETRY );
246   for( ; anIterator.More(); anIterator.Next() )
247   {
248     Handle(HYDROData_Bathymetry) aBathymetryObj =
249       Handle(HYDROData_Bathymetry)::DownCast( anIterator.Current() );
250     if( !aBathymetryObj.IsNull() )
251       createObject( aBathymetryRootObj, aBathymetryObj );
252   }
253
254   LightApp_DataObject* aCalculRootObj = createObject( aRootObj, "CALCULATION CASES" );
255
256   anIterator = HYDROData_Iterator( aDocument, KIND_CALCULATION );
257   for( ; anIterator.More(); anIterator.Next() )
258   {
259     Handle(HYDROData_Calculation) aCalculObj =
260       Handle(HYDROData_Calculation)::DownCast( anIterator.Current() );
261     if( !aCalculObj.IsNull() )
262       createObject( aCalculRootObj, aCalculObj );
263   }
264
265   LightApp_DataObject* aPolylineRootObj = createObject( aRootObj, "POLYLINES" );
266
267   anIterator = HYDROData_Iterator( aDocument, KIND_POLYLINE );
268   for( ; anIterator.More(); anIterator.Next() )
269   {
270     Handle(HYDROData_Polyline) aPolylineObj =
271       Handle(HYDROData_Polyline)::DownCast( anIterator.Current() );
272     if( !aPolylineObj.IsNull() )
273       createObject( aPolylineRootObj, aPolylineObj );
274   }
275
276   LightApp_DataObject* aVisualStateRootObj = createObject( aRootObj, "VISUAL_STATES" );
277
278   anIterator = HYDROData_Iterator( aDocument, KIND_VISUAL_STATE );
279   for( ; anIterator.More(); anIterator.Next() )
280   {
281     Handle(HYDROData_VisualState) aVisualStateObj =
282       Handle(HYDROData_VisualState)::DownCast( anIterator.Current() );
283     if( !aVisualStateObj.IsNull() )
284       createObject( aVisualStateRootObj, aVisualStateObj );
285   }
286
287   if( SUIT_DataBrowser* anObjectBrowser = anApp->objectBrowser() )
288   {
289     anObjectBrowser->setAutoOpenLevel( 3 );
290     anObjectBrowser->openLevels();
291   }
292 }
293
294 HYDROGUI_DataObject* HYDROGUI_DataModel::getDataObject( const Handle(HYDROData_Object)& theModelObject )
295 {
296   return NULL; // to do if necessary
297 }
298
299 HYDROGUI_DataObject* HYDROGUI_DataModel::getReferencedDataObject( HYDROGUI_DataObject* theObject )
300 {
301   return NULL; // to do if necessary
302 }
303
304 SUIT_DataObject* HYDROGUI_DataModel::findObject( const QString& theEntry ) const
305 {
306   LightApp_Application* anApp = dynamic_cast<LightApp_Application*>( module()->application() );
307   return anApp ? anApp->findObject( theEntry ) : 0;
308 }
309
310 void HYDROGUI_DataModel::update( LightApp_DataObject* theObject,
311                                  LightApp_Study* theStudy )
312 {
313   if( !theStudy )
314     theStudy = dynamic_cast<LightApp_Study*>( module()->application()->activeStudy()) ;
315   if( theStudy )
316     update( theStudy->id() );
317 }
318
319 CAM_DataObject* HYDROGUI_DataModel::createRootModuleObject( SUIT_DataObject* theParent )
320 {
321   CAM_DataObject* aRootObj = createModuleObject( theParent );
322   setRoot( aRootObj );
323   return aRootObj;
324 }
325
326 void HYDROGUI_DataModel::updateModel()
327 {
328   HYDROGUI_Module* aModule = dynamic_cast<HYDROGUI_Module*>( module() );
329   if( aModule )
330     update( aModule->getStudyId() );
331 }
332
333 Handle(HYDROData_Object) HYDROGUI_DataModel::objectByEntry( const QString& theEntry,
334                                                             const ObjectKind theObjectKind )
335 {
336   QString anEntry = theEntry;
337   if( anEntry.indexOf( "_" ) != -1 ) // reference object
338     anEntry = anEntry.section( "_", -1 );
339
340   Handle(HYDROData_Document) aDocument = getDocument();
341   if( !aDocument.IsNull() )
342   {
343     HYDROData_Iterator anIterator( aDocument, theObjectKind );
344     for( ; anIterator.More(); anIterator.Next() )
345     {
346       Handle(HYDROData_Object) anObject = anIterator.Current();
347       if( !anObject.IsNull() )
348       {
349         QString anEntryRef = HYDROGUI_DataObject::dataObjectEntry( anObject );
350         if( anEntryRef == anEntry )
351           return anObject;
352       }
353     }
354   }
355   return NULL;
356 }
357
358 bool HYDROGUI_DataModel::canUndo() const
359 {
360   return getDocument()->CanUndo();
361 }
362
363 bool HYDROGUI_DataModel::canRedo() const
364 {
365   return getDocument()->CanRedo();
366 }
367
368 QStringList HYDROGUI_DataModel::undoNames() const
369 {
370   QStringList aNames;
371   for( TDF_ListIteratorOfDeltaList anIter( getDocument()->GetUndos() ); anIter.More(); anIter.Next() )
372     aNames.prepend( HYDROGUI_Tool::ToQString( anIter.Value()->Name() ) );
373   return aNames;
374 }
375
376 QStringList HYDROGUI_DataModel::redoNames() const
377 {
378   QStringList aNames;
379   for( TDF_ListIteratorOfDeltaList anIter( getDocument()->GetRedos() ); anIter.More(); anIter.Next() )
380     aNames.append( HYDROGUI_Tool::ToQString( anIter.Value()->Name() ) );
381   return aNames;
382 }
383
384 void HYDROGUI_DataModel::clearUndos()
385 {
386   getDocument()->ClearUndos();
387 }
388
389 void HYDROGUI_DataModel::clearRedos()
390 {
391   getDocument()->ClearRedos();
392 }
393
394 bool HYDROGUI_DataModel::undo()
395 {
396   try 
397   {
398     getDocument()->Undo();
399   }
400   catch ( Standard_Failure )
401   {
402     return false;
403   }
404   return true;
405 }
406
407 bool HYDROGUI_DataModel::redo()
408 {
409   try 
410   {
411     getDocument()->Redo();
412   }
413   catch ( Standard_Failure )
414   {
415     return false;
416   }
417   return true;
418 }
419
420 bool HYDROGUI_DataModel::canCopy()
421 {
422   HYDROData_SequenceOfObjects aSeq = HYDROGUI_Tool::GetSelectedObjects( (HYDROGUI_Module*)module() );
423   if( aSeq.Length() != 1 )
424     return false;
425
426   Handle(HYDROData_Object) anObject = aSeq.First();
427   if( anObject.IsNull() )
428     return false;
429
430   ObjectKind aKind = anObject->GetKind();
431   if( aKind == KIND_IMAGE ||
432       aKind == KIND_POLYLINE ||
433       aKind == KIND_CALCULATION )
434     return true;
435
436   return false;
437 }
438
439 bool HYDROGUI_DataModel::canPaste()
440 {
441   for( int anIndex = 1, aLength = myCopyingObjects.Length(); anIndex <= aLength; anIndex++ )
442   {
443     Handle(HYDROData_Object) anObject = myCopyingObjects.Value( anIndex );
444     if( !anObject.IsNull() && !anObject->IsRemoved() )
445       return true;
446   }
447   return false;
448 }
449
450 bool HYDROGUI_DataModel::copy()
451 {
452   HYDROData_SequenceOfObjects aSeq = HYDROGUI_Tool::GetSelectedObjects( (HYDROGUI_Module*)module() );
453   changeCopyingObjects( aSeq );
454   return true;
455 }
456
457 bool HYDROGUI_DataModel::paste()
458 {
459   bool anIsChanged = false;
460   for( int anIndex = 1, aLength = myCopyingObjects.Length(); anIndex <= aLength; anIndex++ )
461   {
462     Handle(HYDROData_Object) anObject = myCopyingObjects.Value( anIndex );
463     if( !anObject.IsNull() && !anObject->IsRemoved() )
464     {
465       ObjectKind aKind = anObject->GetKind();
466       Handle(HYDROData_Object) aClone = getDocument()->CreateObject( aKind );
467       if( !aClone.IsNull() )
468       {
469         anObject->CopyTo( aClone );
470         anIsChanged = true;
471
472         // generate a new unique name for the clone object:
473         // case 1: Image_1 -> Image_2
474         // case 2: ImageObj -> ImageObj_1
475         QString aName = aClone->GetName();
476         QString aPrefix = aName;
477         if( aName.contains( '_' ) ) // case 1
478         {
479           QString aSuffix = aName.section( '_', -1 );
480           bool anIsInteger = false;
481           aSuffix.toInt( &anIsInteger );
482           if( anIsInteger )
483             aPrefix = aName.section( '_', 0, -2 );
484         }
485         else // case 2
486           aPrefix = aName;
487         aName = HYDROGUI_Tool::GenerateObjectName( (HYDROGUI_Module*)module(), aPrefix );
488         aClone->SetName( aName );
489       }
490     }
491   }
492   return anIsChanged;
493 }
494
495 void HYDROGUI_DataModel::changeCopyingObjects( const HYDROData_SequenceOfObjects& theSeq )
496 {
497   myCopyingObjects.Assign( theSeq );
498 }
499
500 Handle(HYDROData_Document) HYDROGUI_DataModel::getDocument() const
501 {
502   int aStudyId = module()->application()->activeStudy()->id();
503   return HYDROData_Document::Document( aStudyId );
504 }
505
506 LightApp_DataObject* HYDROGUI_DataModel::createObject( SUIT_DataObject* theParent,
507                                                        Handle(HYDROData_Object) theModelObject,
508                                                        const QString& theParentEntry )
509 {
510   return new HYDROGUI_DataObject( theParent, theModelObject, theParentEntry );
511 }
512
513 LightApp_DataObject* HYDROGUI_DataModel::createObject( SUIT_DataObject* theParent,
514                                                        const QString& theName )
515 {
516   return new HYDROGUI_NamedObject( theParent, theName );
517 }
518
519 void HYDROGUI_DataModel::removeChild( SUIT_DataObject* theParent,
520                                       SUIT_DataObject* theChild )
521 {
522   SUIT_DataObject* aSubChild = theChild->firstChild();
523   for( ; aSubChild; aSubChild = aSubChild->nextBrother() )
524     removeChild( theChild, aSubChild );
525   theParent->removeChild( theChild );
526 }
527
528 SUIT_DataObject* HYDROGUI_DataModel::findChildByName( const SUIT_DataObject* theFather,
529                                                       const QString& theName )
530 {
531   SUIT_DataObject* aChild = theFather->firstChild();
532   while( aChild )
533   {
534     if( aChild->name() == theName )
535       return aChild; // found
536     aChild = aChild->nextBrother();
537   }
538   return NULL; // not found
539 }