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