Salome HOME
97be8db880beb89c923cac1c3c1ce5b215e64bba
[modules/gui.git] / src / SalomeApp / SalomeApp_Study.cxx
1 #include "SalomeApp_Study.h"
2
3 #include "SalomeApp_Module.h"
4 #include "SalomeApp_DataModel.h"
5 #include "LightApp_RootObject.h"
6 #include "SalomeApp_DataObject.h"
7 #include "SalomeApp_Application.h"
8 #include "SalomeApp_Engine_i.hxx"
9
10 #include <OB_Browser.h>
11
12 #include <SUIT_ResourceMgr.h>
13
14 #include <qptrlist.h>
15
16 #include "utilities.h"
17 #include "string.h"
18 #include "vector.h"
19
20 #include "SALOMEDS_Tool.hxx"
21
22 #include <SALOMEconfig.h>
23 #include CORBA_SERVER_HEADER(SALOME_Exception)
24
25 /*!
26   Constructor.
27 */
28 SalomeApp_Study::SalomeApp_Study( SUIT_Application* app )
29 : LightApp_Study( app )
30 {
31 }  
32
33 /*!
34   Destructor.
35 */
36 SalomeApp_Study::~SalomeApp_Study()
37 {
38 }
39
40 /*!
41   Gets study id.
42 */
43 int SalomeApp_Study::id() const
44 {
45   int id = -1;
46   if ( myStudyDS )
47     id = studyDS()->StudyId();
48   return id;
49 }
50
51 /*!
52   Gets studyDS pointer.
53 */
54 _PTR(Study) SalomeApp_Study::studyDS() const
55 {
56   return myStudyDS;
57 }
58
59 /*!
60   Create document.
61 */
62 void SalomeApp_Study::createDocument()
63 {
64   MESSAGE( "openDocument" );
65
66   // initialize myStudyDS, read HDF file
67   QString aName = newStudyName();
68   _PTR(Study) study ( SalomeApp_Application::studyMgr()->NewStudy( aName.latin1() ) );
69   if ( !study )
70     return;
71
72   setStudyDS( study );
73   setStudyName( aName );
74
75   LightApp_Study::createDocument();
76 }
77
78 //=======================================================================
79 // name    : openDocument
80 /*! Purpose : Open document*/
81 //=======================================================================
82 bool SalomeApp_Study::openDocument( const QString& theFileName )
83 {
84   MESSAGE( "openDocument" );
85
86   // initialize myStudyDS, read HDF file
87   _PTR(Study) study ( SalomeApp_Application::studyMgr()->Open( (char*) theFileName.latin1() ) );
88   if ( !study )
89     return false;
90
91   setStudyDS( study );
92
93   bool res = LightApp_Study::openDocument( theFileName );
94   
95   return res;
96 }
97
98 //=======================================================================
99 // name    : loadDocument
100 /*! Purpose : Connects GUI study to SALOMEDS one already loaded into StudyManager*/
101 //=======================================================================
102 bool SalomeApp_Study::loadDocument( const QString& theStudyName )
103 {
104   MESSAGE( "loadDocument" );
105
106   // obtain myStudyDS from StudyManager
107   _PTR(Study) study ( SalomeApp_Application::studyMgr()->GetStudyByName( (char*) theStudyName.latin1() ) );
108   if ( !study )
109     return false;
110
111   setStudyDS( study );
112
113   bool res = LightApp_Study::loadDocument( theStudyName );
114
115   return res;
116 }
117
118 //=======================================================================
119 // name    : saveDocumentAs
120 /*! Purpose : Save document*/
121 //=======================================================================
122 bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
123 {
124   // save SALOMEDS document
125   SUIT_ResourceMgr* resMgr = application()->resourceMgr();
126   if( !resMgr )
127     return false;
128   bool res = LightApp_Study::saveDocumentAs( theFileName );  //SRN: BugID IPAL9377, removed usage of uninitialized variable <res>
129
130   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ),
131        isAscii = resMgr->booleanValue( "Study", "ascii_file", true );
132   isAscii ? SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.latin1(), studyDS(), isMultiFile ) :
133             SalomeApp_Application::studyMgr()->SaveAs     ( theFileName.latin1(), studyDS(), isMultiFile );
134
135   return res;
136 }
137
138 //=======================================================================
139 // name    : saveDocument
140 /*! Purpose : Save document*/
141 //=======================================================================
142 void SalomeApp_Study::saveDocument()
143 {
144   // save SALOMEDS document
145   SUIT_ResourceMgr* resMgr = application()->resourceMgr();
146   if( !resMgr )
147     return;
148   LightApp_Study::saveDocument();
149   
150   bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ),
151        isAscii = resMgr->booleanValue( "Study", "ascii_file", true );
152   isAscii ? SalomeApp_Application::studyMgr()->SaveASCII( studyDS(), isMultiFile ) :
153             SalomeApp_Application::studyMgr()->Save     ( studyDS(), isMultiFile );
154 }
155
156 //================================================================
157 // Function : closeDocument
158 /*! Purpose  : Close document*/
159 //================================================================
160 void SalomeApp_Study::closeDocument(bool permanently)
161 {
162   LightApp_Study::closeDocument(permanently);
163
164   // close SALOMEDS document
165   _PTR(Study) studyPtr = studyDS();
166   if ( studyPtr )
167   {
168     if(permanently) SalomeApp_Application::studyMgr()->Close( studyPtr );
169     SALOMEDSClient_Study* aStudy = 0;
170     setStudyDS( _PTR(Study)(aStudy) );
171   }
172 }
173
174 //================================================================
175 // Function : isModified
176 // Purpose  : 
177 //================================================================
178 bool SalomeApp_Study::isModified() const
179 {
180   bool isAnyChanged = studyDS() && studyDS()->IsModified();
181   if (!isAnyChanged)
182     isAnyChanged = LightApp_Study::isModified();
183
184   return isAnyChanged; 
185 }
186
187 //================================================================
188 // Function : isSaved
189 /*! Purpose  : Check: data model is saved?*/
190 //================================================================
191 bool SalomeApp_Study::isSaved() const
192 {
193   bool isAllSaved = studyDS() && studyDS()->GetPersistentReference().size();
194   if (!isAllSaved)
195     isAllSaved = LightApp_Study::isModified();
196
197   return isAllSaved; 
198 }
199
200 /*!
201   Set studyDS.
202 */
203 void SalomeApp_Study::setStudyDS( const _PTR(Study)& s )
204 {
205   myStudyDS = s;
206 }
207
208 /*!
209   Insert data model.
210 */
211 void SalomeApp_Study::dataModelInserted (const CAM_DataModel* dm)
212 {
213   MESSAGE("SalomeApp_Study::dataModelInserted() : module name() = " << dm->module()->name());
214
215   CAM_Study::dataModelInserted(dm);
216
217   // Create SComponent for module, using default engine (CORBAless)
218   //  SalomeApp_Module* aModule = (SalomeApp_Module*)(dm->module());
219   SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
220   // 1. aModule == 0 means that this is a light module (no CORBA enigine)
221   // 2. engineIOR == "" means this is a full module but without CORBA engine
222   if (!aModule || aModule->engineIOR().isEmpty()) {
223     // Check SComponent existance
224     _PTR(Study) aStudy = studyDS();
225     if (!aStudy) 
226       return;
227     _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name());
228     if (!aComp) {
229       // Create SComponent
230       _PTR(StudyBuilder) aBuilder = studyDS()->NewBuilder();
231       aComp = aBuilder->NewComponent(dm->module()->name());
232       
233       // Set default engine IOR
234       aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().latin1());
235     }
236   }
237 }
238
239 /*!
240   Open data model
241 */
242 bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm )
243 {
244   if (!dm)
245     return false;
246
247   //  SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm);
248   SalomeApp_Module* aModule = dynamic_cast<SalomeApp_Module*>( dm->module() );
249   _PTR(Study)       aStudy = studyDS(); // shared_ptr cannot be used here
250   _PTR(SComponent)  aSComp;
251   QString anEngine;
252   // 1. aModule == 0 means that this is a light module (no CORBA enigine)
253   // 2. engineIOR == "" means this is a full module but without CORBA engine
254   if (!aModule || aModule->engineIOR().isEmpty()) {
255     anEngine = SalomeApp_Application::defaultEngineIOR();
256     aSComp = aStudy->FindComponent(dm->module()->name());
257   }
258   else {
259     SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
260     if ( aDM ) {
261       QString anId = aDM->getRootEntry( this );
262       if ( anId.isEmpty() )
263         return true; // Probably nothing to load
264
265       if ( aDM ) {
266         anEngine = aDM->getModule()->engineIOR();
267         if ( anEngine == "-1" ) {
268           // Module doesn't have a CORBA engine and doesn't use
269           // a default one -> SALOMEDS persistence cannot be used
270           return false;
271         }
272       }
273       if ( anEngine.isEmpty() ) {
274         // Module use a default engine
275         //TODO: deside, if the below code has to be copyed in a light data model to avoid bulding of data tree twice
276         anEngine = SalomeApp_Application::defaultEngineIOR();
277       }
278       aSComp = aStudy->FindComponentID( std::string( anId.latin1() ) );
279     }
280   }
281   if ( aSComp ) {
282     _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() );
283     if ( aBuilder ) {
284       try {
285         aBuilder->LoadWith( aSComp, std::string( anEngine.latin1() ) );
286       }
287       catch( const SALOME::SALOME_Exception& ) {
288         // Oops, something went wrong while loading -> return an error
289         return false;
290       }
291       // Something has been read -> create data model tree
292       // aDM->buildTree( aSComp, 0, this );
293     }
294   } else {
295     // Don't return false here, for there might be no data
296     // for a given component in the study yet
297   }
298   if (dm && dm->open(studyName, this)) {
299     // Something has been read -> create data model tree
300     LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>( dm );
301     if ( aDM )
302       aDM->update(NULL, this);
303     return true;
304   }
305   return false;
306 }
307
308 /*!
309   Create new study name.
310 */
311 QString SalomeApp_Study::newStudyName() const
312 {
313   std::vector<std::string> studies = SalomeApp_Application::studyMgr()->GetOpenStudies();
314   QString prefix( "Study%1" ), newName, curName;
315   int i = 1, j, n = studies.size();
316   while ( newName.isEmpty() ){
317     curName = prefix.arg( i );
318     for ( j = 0 ; j < n; j++ ){
319       if ( !strcmp( studies[j].c_str(), curName.latin1() ) )
320         break;
321     }
322     if ( j == n )
323       newName = curName;
324     else
325       i++;
326   }
327   return newName;
328 }
329
330 //================================================================
331 // Function : GetListOfFiles
332 /*! Purpose  : to be used by CORBAless modules*/
333 //================================================================
334 std::vector<std::string> SalomeApp_Study::GetListOfFiles() const
335 {
336   SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
337   if (aDefaultEngine) {
338     const char* aName = ((CAM_Application*)application())->activeModule()->name();
339     return aDefaultEngine->GetListOfFiles(id(), aName);
340   }
341
342   std::vector<std::string> aListOfFiles;
343   return aListOfFiles;
344 }
345
346 //================================================================
347 // Function : SetListOfFiles
348 /*! Purpose  : to be used by CORBAless modules*/
349 //================================================================
350 void SalomeApp_Study::SetListOfFiles (const std::vector<std::string> theListOfFiles)
351 {
352   SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
353   if (aDefaultEngine) {
354     const char* aName = ((CAM_Application*)application())->activeModule()->name();
355     aDefaultEngine->SetListOfFiles(theListOfFiles, id(), aName);
356   }
357 }
358
359 //================================================================
360 // Function : GetTmpDir
361 /*! Purpose  : to be used by CORBAless modules*/
362 //================================================================
363 std::string SalomeApp_Study::GetTmpDir (const char* theURL,
364                                             const bool  isMultiFile)
365 {
366   std::string anURLDir = SALOMEDS_Tool::GetDirFromPath(theURL);
367   std::string aTmpDir = isMultiFile ? anURLDir : SALOMEDS_Tool::GetTmpDir();
368   return aTmpDir;
369 }
370
371 //================================================================
372 // Function : RemoveTemporaryFiles
373 /*! Purpose  : to be used by CORBAless modules*/
374 //================================================================
375 void SalomeApp_Study::RemoveTemporaryFiles (const bool isMultiFile) const
376 {
377   if (isMultiFile)
378     return;
379
380   std::vector<std::string> aListOfFiles = GetListOfFiles();
381   if (aListOfFiles.size() > 0) {
382     std::string aTmpDir = aListOfFiles[0];
383
384     const int n = aListOfFiles.size() - 1;
385     SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
386     aSeq->length(n);
387     for (int i = 0; i < n; i++)
388       aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str());
389
390     SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
391   }
392 }
393
394 // END: methods to be used by CORBAless modules
395
396 void SalomeApp_Study::deleteReferencesTo( _PTR( SObject ) obj )
397 {
398   _PTR(StudyBuilder) sb = studyDS()->NewBuilder();
399   std::vector<_PTR(SObject)> aRefs = studyDS()->FindDependances( obj );
400   for( int i=0, n=aRefs.size(); i<n; i++ )
401   {
402     _PTR( SObject ) o = aRefs[i];
403     if( o->GetFatherComponent()->ComponentDataType()==obj->GetFatherComponent()->ComponentDataType() )
404     {
405       sb->RemoveReference( o );
406       sb->RemoveObjectWithChildren( o );
407     }
408   }
409 }
410