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