Salome HOME
Update from BR_V5_DEV 13Feb2009
[modules/gui.git] / src / LightApp / LightApp_Study.cxx
1 //  Copyright (C) 2007-2008  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 #include "LightApp_Study.h"
23
24 #include "CAM_DataModel.h"
25 #include "CAM_Module.h"
26 #include "LightApp_Application.h"
27 #include "LightApp_DataModel.h"
28 #include "LightApp_DataObject.h"
29 #include "LightApp_HDFDriver.h"
30
31 #include "SUIT_ResourceMgr.h"
32 #include "SUIT_DataObjectIterator.h"
33
34 #include <set>
35 #include <QString>
36
37 /*!
38   Constructor.
39 */
40 LightApp_Study::LightApp_Study( SUIT_Application* app )
41 : CAM_Study( app )
42 {
43   // HDF persistence
44   myDriver = new LightApp_HDFDriver();
45   //myDriver = new LightApp_Driver();
46 }
47
48 /*!
49   Destructor.
50 */
51 LightApp_Study::~LightApp_Study()
52 {
53 }
54
55 /*!
56   Create document.
57 */
58 bool LightApp_Study::createDocument( const QString& theStr )
59 {
60   setStudyName( QString( "Study%1" ).arg( LightApp_Application::studyId() ) );
61
62   // create myRoot
63   setRoot( new LightApp_RootObject( this ) );
64
65   bool aRet = CAM_Study::createDocument( theStr );
66
67   emit created( this );
68
69   return aRet;
70 }
71
72 /*!
73   Opens document
74 */
75 bool LightApp_Study::openDocument( const QString& theFileName )
76 {
77   myDriver->ClearDriverContents();
78   // create files for models from theFileName
79   if( !openStudyData(theFileName))
80     return false;
81
82   setRoot( new LightApp_RootObject( this ) ); // create myRoot
83
84   // update loaded data models: call open() and update() on them.
85   ModelList dm_s;
86   dataModels( dm_s );
87   QListIterator<CAM_DataModel*> it( dm_s );
88   while ( it.hasNext() )
89     openDataModel( studyName(), it.next() );
90   // this will build a SUIT_DataObject-s tree under myRoot member field
91   // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
92   // but tree that corresponds to not-loaded data models will be updated any way. 
93   ((LightApp_Application*)application())->updateObjectBrowser( false ); 
94
95   bool res = CAM_Study::openDocument( theFileName );
96
97   emit opened( this );
98   return res;
99 }
100
101 /*!
102   Loads document
103 */
104 bool LightApp_Study::loadDocument( const QString& theStudyName )
105 {
106   myDriver->ClearDriverContents();
107   if( !openStudyData(theStudyName))
108     return false;
109
110   setRoot( new LightApp_RootObject( this ) ); // create myRoot
111
112   //SRN: BugID IPAL9021, put there the same code as in a method openDocument
113
114   // update loaded data models: call open() and update() on them.
115   ModelList dm_s;
116   dataModels( dm_s );
117
118   QListIterator<CAM_DataModel*> it( dm_s );
119   while ( it.hasNext() )
120     openDataModel( studyName(), it.next() );
121
122   // this will build a SUIT_DataObject-s tree under myRoot member field
123   // passing "false" in order NOT to rebuild existing data models' trees - it was done in previous step
124   // but tree that corresponds to not-loaded data models will be updated any way. 
125   ((LightApp_Application*)application())->updateObjectBrowser( false ); 
126
127   bool res = CAM_Study::openDocument( theStudyName );
128   emit opened( this );
129   //SRN: BugID IPAL9021: End
130   return res;
131 }
132
133 /*!
134   Saves document
135 */
136 bool LightApp_Study::saveDocumentAs( const QString& theFileName )
137 {
138   SUIT_ResourceMgr* resMgr = application()->resourceMgr();
139   if( !resMgr )
140     return false;
141
142   ModelList list; 
143   dataModels( list );
144
145   QStringList listOfFiles;
146   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
147   QListIterator<CAM_DataModel*> itList( list );
148   while ( itList.hasNext() )
149   {
150     LightApp_DataModel* aModel = (LightApp_DataModel*)itList.next();
151     if ( !aModel ) continue;
152
153     std::vector<std::string> anOldList = myDriver->GetListOfFiles( aModel->module()->name().toLatin1().constData() );
154     listOfFiles.clear();
155     aModel->saveAs( theFileName, this, listOfFiles );
156     if ( !listOfFiles.isEmpty() )
157       saveModuleData(aModel->module()->name(), listOfFiles);
158
159     // Remove files if necessary. File is removed if it was in the list of files before
160     // saving and it is not contained in the list after saving. This provides correct 
161     // removing previous temporary files. These files are not removed before saving
162     // because they may be required for it.
163
164     std::vector<std::string> aNewList = myDriver->GetListOfFiles( aModel->module()->name().toLatin1().constData() );
165     
166     std::set<std::string> aNewNames;
167     std::set<std::string> toRemove;
168     int i, n;
169     for( i = 0, n = aNewList.size(); i < n; i++ )
170       aNewNames.insert( aNewList[ i ] );
171     for( i = 0, n = anOldList.size(); i < n; i++ )
172     {
173       if ( i == 0 ) // directory is always inserted in list
174         toRemove.insert( anOldList[ i ] );
175       else if ( aNewNames.find( anOldList[ i ] ) == aNewNames.end() )
176         toRemove.insert( anOldList[ i ] );
177     }
178         
179     std::vector<std::string> toRemoveList( toRemove.size() );
180     std::set<std::string>::iterator anIter;
181     for( anIter = toRemove.begin(), i = 0; anIter != toRemove.end(); ++anIter, ++i )
182       toRemoveList[ i ] = *anIter;
183
184     
185     myDriver->RemoveFiles( toRemoveList, isMultiFile );
186   }
187
188   bool res = saveStudyData(theFileName);
189   res = res && CAM_Study::saveDocumentAs( theFileName );
190   //SRN: BugID IPAL9377, removed usage of uninitialized variable <res>
191   if ( res )
192     emit saved( this );
193
194   return res;
195 }
196
197 /*!
198   Saves document
199 */
200 bool LightApp_Study::saveDocument()
201 {
202   ModelList list; dataModels( list );
203
204   myDriver->ClearDriverContents();
205   QStringList listOfFiles;
206   QListIterator<CAM_DataModel*> itList( list );
207   while ( itList.hasNext() ) {
208     LightApp_DataModel* aModel = (LightApp_DataModel*)itList.next();
209     if ( !aModel ) continue;
210
211     listOfFiles.clear();
212     aModel->save( listOfFiles );
213     saveModuleData(aModel->module()->name(), listOfFiles);
214   }
215
216   bool res = saveStudyData(studyName());
217   res = res && CAM_Study::saveDocument();
218   if (res)
219     emit saved( this );
220
221   return res;
222 }
223
224 /*!
225   Closes document
226 */
227 void LightApp_Study::closeDocument(bool permanently)
228 {
229   // Inform everybody that this study is going to close when it's most safe to,
230   // i.e. in the very beginning
231   emit closed( this );
232
233   CAM_Study::closeDocument(permanently);
234   
235   // Remove temporary files
236   myDriver->ClearDriverContents();
237 }
238
239 /*!
240   \return real entry by entry of reference
241   \param entry - entry of reference object
242 */
243 QString LightApp_Study::referencedToEntry( const QString& entry ) const
244 {
245   return entry;
246 }
247
248 /*!
249   \return entries of object children
250 */
251 void LightApp_Study::children( const QString&, QStringList& ) const
252 {
253 }
254
255 /*!
256   \return true if entry corresponds to component
257 */
258 bool LightApp_Study::isComponent( const QString& entry ) const
259 {
260   if( !root() )
261     return false;
262
263   DataObjectList ch;
264   root()->children( ch );
265   DataObjectList::const_iterator anIt = ch.begin(), aLast = ch.end();
266   for( ; anIt!=aLast; anIt++ )
267   {
268     LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( *anIt );
269     if( obj && obj->entry()==entry )
270       return true;
271   }
272   return false;
273 }
274
275 /*!
276   \return component data type for entry
277 */
278 QString LightApp_Study::componentDataType( const QString& entry ) const
279 {
280   LightApp_DataObject* aCurObj;
281   for ( SUIT_DataObjectIterator it( root(), SUIT_DataObjectIterator::DepthLeft ); it.current(); ++it ) {
282     aCurObj = dynamic_cast<LightApp_DataObject*>( it.current() );
283     if ( aCurObj && aCurObj->entry() == entry ) {
284       return aCurObj->componentDataType();
285     }
286   }
287   return "";
288 }
289
290 /*!
291   \return true if study is modified
292 */
293 bool LightApp_Study::isModified() const
294 {
295   bool isAnyChanged = CAM_Study::isModified();
296   ModelList list; dataModels( list );
297
298   LightApp_DataModel* aModel = 0;
299   QListIterator<CAM_DataModel*> it( list );
300   while ( it.hasNext() && !isAnyChanged ) {
301     aModel = dynamic_cast<LightApp_DataModel*>( it.next() );
302     if ( aModel )
303       isAnyChanged = aModel->isModified();
304   }
305   return isAnyChanged; 
306 }
307
308 /*!
309   \return true if data model is saved
310 */
311 bool LightApp_Study::isSaved() const
312 {
313   return CAM_Study::isSaved();
314 }
315
316 /*!
317   Creates SComponent for module, necessary for SalomeApp study
318 */
319 void LightApp_Study::addComponent(const CAM_DataModel* dm)
320 {
321 }
322
323 /*!
324   Saves list file for module 'theModuleName'
325 */
326 void LightApp_Study::saveModuleData(QString theModuleName, QStringList theListOfFiles)
327 {
328   int aNb = theListOfFiles.count();
329   if ( aNb == 0 )
330     return;
331
332   std::vector<std::string> aListOfFiles ( aNb );
333   int anIndex = 0;
334   for ( QStringList::Iterator it = theListOfFiles.begin(); it != theListOfFiles.end(); ++it ) {
335     if ( (*it).isEmpty() )
336       continue;
337     aListOfFiles[anIndex] = (*it).toLatin1().constData();
338     anIndex++;
339   }
340   myDriver->SetListOfFiles(theModuleName.toLatin1().constData(), aListOfFiles);
341 }
342
343 /*!
344   Gets list of file for module 'theModuleNam'
345 */
346 void LightApp_Study::openModuleData(QString theModuleName, QStringList& theListOfFiles)
347 {
348   std::vector<std::string> aListOfFiles =  myDriver->GetListOfFiles(theModuleName.toLatin1().constData());
349   int i, aLength = aListOfFiles.size() - 1;
350   if (aLength < 0)
351     return;
352
353   //Get a temporary directory for saved a file
354   theListOfFiles.append(aListOfFiles[0].c_str());
355   for(i = 0; i < aLength; i++)
356     theListOfFiles.append(aListOfFiles[i+1].c_str());
357 }
358
359 /*!
360   Saves data from study
361 */
362 bool LightApp_Study::saveStudyData( const QString& theFileName )
363 {
364   ModelList list; dataModels( list );
365   SUIT_ResourceMgr* resMgr = application()->resourceMgr();
366   if( !resMgr )
367     return false;
368   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
369
370   bool aRes = myDriver->SaveDatasInFile(theFileName.toLatin1(), isMultiFile);
371   return aRes;
372 }
373
374 /*!
375   Opens data for study
376 */
377 bool LightApp_Study::openStudyData( const QString& theFileName )
378 {
379   SUIT_ResourceMgr* resMgr = application()->resourceMgr();
380   if( !resMgr )
381     return false;
382   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false );
383
384   bool aRes = myDriver->ReadDatasFromFile(theFileName.toLatin1(), isMultiFile);
385   return aRes;
386 }
387
388 /*!
389   Opens data model
390 */
391 bool LightApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm )
392 {
393   if (!dm)
394     return false;
395
396   QStringList listOfFiles;
397   openModuleData(dm->module()->name(), listOfFiles);
398   if (dm && dm->open(studyName, this, listOfFiles)) {
399     // Something has been read -> create data model tree
400     LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>( dm );
401     if ( aDM )
402       aDM->update(NULL, this);
403     return true;
404   }
405   return false;
406 }
407
408 /*!
409   \return temporary directory for saving files of modules
410 */
411 std::string LightApp_Study::GetTmpDir (const char* theURL,
412                                        const bool  isMultiFile)
413 {
414   return myDriver->GetTmpDir(theURL, isMultiFile);
415 }
416
417 /*!
418   \return list of files necessary for module
419   \param theModuleName - name of module
420 */
421 std::vector<std::string> LightApp_Study::GetListOfFiles(const char* theModuleName) const
422 {
423   std::vector<std::string> aListOfFiles;
424   aListOfFiles = myDriver->GetListOfFiles(theModuleName);
425   return aListOfFiles;
426 }
427
428 /*!
429   Sets list of files necessary for module
430   \param theModuleName - name of module
431   \param theListOfFiles - list of files
432 */
433 void LightApp_Study::SetListOfFiles (const char* theModuleName, const std::vector<std::string> theListOfFiles)
434 {
435   myDriver->SetListOfFiles(theModuleName, theListOfFiles);
436 }
437
438 /*!
439   Removes temporary files
440 */
441 void LightApp_Study::RemoveTemporaryFiles (const char* theModuleName, const bool isMultiFile) const
442 {
443   if (isMultiFile)
444     return;
445   bool isDirDeleted = true;
446   myDriver->RemoveTemporaryFiles(theModuleName, isDirDeleted);
447 }
448
449 /*!
450   Fills list with components names
451   \param comp - list to be filled
452 */
453 void LightApp_Study::components( QStringList& comp ) const
454 {
455   DataObjectList children = root()->children();
456   DataObjectList::const_iterator anIt = children.begin(), aLast = children.end();
457   for( ; anIt!=aLast; anIt++ )
458   {
459     LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( *anIt );
460     if( obj && obj->entry()!="Interface Applicative" )
461       comp.append( obj->entry() );
462   }
463 }