Salome HOME
703995a5516ebe2749a1ea1a0468c3749f265422
[modules/gui.git] / src / SalomeApp / SalomeApp_DataModel.cxx
1 // File:      SalomeApp_DataModel.cxx
2 // Created:   10/25/2004 10:36:06 AM
3 // Author:    Sergey LITONIN
4 // Copyright (C) CEA 2004
5
6 #include "SalomeApp_DataModel.h"
7 #include "SalomeApp_Study.h"
8 #include "SalomeApp_RootObject.h"
9 #include "SalomeApp_DataObject.h"
10 #include "SalomeApp_Module.h"
11 #include "SalomeApp_Application.h"
12 #include "SalomeApp_SelectionMgr.h"
13 #include "SalomeApp_Engine_i.hxx"
14
15 #include <CAM_DataObject.h>
16
17 #include <SUIT_Application.h>
18 #include <SUIT_ResourceMgr.h>
19 #include <SUIT_Session.h>
20
21 #include "SALOMEDS_Tool.hxx"
22
23 #include <SALOMEconfig.h>
24 #include CORBA_SERVER_HEADER(SALOME_Exception)
25
26 //=======================================================================
27 // name    : BuildTree
28 /*!Purpose : static method used by SalomeApp_Study and SalomeApp_DataModel classes
29  *           to create default SALOMEDS-based data object tree
30  */
31 //=======================================================================
32 SUIT_DataObject* SalomeApp_DataModel::BuildTree( const _PTR(SObject)& obj,
33                                                  SUIT_DataObject* parent,
34                                                  SalomeApp_Study* study,
35                                                  bool skip  )
36 {
37   SalomeApp_DataObject* aDataObj = 0;
38   if ( !obj || !study )
39     return aDataObj;
40
41   _PTR(SObject) refObj;
42   if ( obj->GetName().size() || obj->ReferencedObject( refObj ) )  // skip nameless non references SObjects
43   {
44     _PTR(SComponent) aSComp( obj );
45
46     // patch for bug IPAL9313
47     if ( aSComp && parent && skip ) 
48     {
49       QString aSName( aSComp->GetName().c_str() );
50       DataObjectList allComponents = parent->children( /*recursive=*/false );
51       for ( DataObjectListIterator it( allComponents ); it.current(); ++it ) {
52         SUIT_DataObject* componentObj = it.current();
53         if ( componentObj->name() == aSName ) {
54           // mkr : modifications for update of already published in object browser, but not loaded yet components
55           // asv : corresponding DataObjects are DELETED before update (so they are re-built). 
56           CAM_Application* anApp = dynamic_cast<CAM_Application*>( SUIT_Session::session()->activeApplication() );
57           if ( anApp && !anApp->module( aSName ) ) { // if module is not loaded, delete it's DataObject
58             delete componentObj; // delete DataObject and re-create it and all its sub-objects
59             break; // proceed to build_a_data_object code below
60             // don't do anything here, because iterator may be corrupted (deleted object inside it)
61           }
62           else
63             return componentObj;
64         }
65       }
66     }
67
68     aDataObj = aSComp ? new SalomeApp_ModuleObject( aSComp, parent ) :
69                         new SalomeApp_DataObject  ( obj, parent );
70
71     _PTR(ChildIterator) it ( study->studyDS()->NewChildIterator( obj ) );
72     for ( ; it->More();it->Next() ) {
73       // don't use shared_ptr here, for Data Object will take
74       // ownership of this pointer
75       _PTR(SObject) aSO( it->Value() );
76       BuildTree( aSO, aDataObj, study );
77     }
78   }
79   return aDataObj;
80 }
81
82 //=======================================================================
83 // name    : SalomeApp_DataModel::SalomeApp_DataModel
84 /*!Purpose : Constructor*/
85 //=======================================================================
86 SalomeApp_DataModel::SalomeApp_DataModel( CAM_Module* theModule )
87 : CAM_DataModel( theModule )
88 {
89 }
90
91 //=======================================================================
92 // name    : SalomeApp_DataModel::~SalomeApp_DataModel
93 /*! Purpose : Destructor*/
94 //=======================================================================
95 SalomeApp_DataModel::~SalomeApp_DataModel()
96 {
97 }
98
99 //================================================================
100 // Function : open
101 /*! Purpose  : Open data model*/
102 //================================================================
103 bool SalomeApp_DataModel::open( const QString&, CAM_Study* study )
104 {
105   SalomeApp_Study* aDoc = dynamic_cast<SalomeApp_Study*>( study );
106   if ( !aDoc )
107     return false;
108
109   QString anId = getRootEntry( aDoc );
110   if ( anId.isEmpty() )
111     return true; // Probably nothing to load
112
113   QString anEngine = getModule()->engineIOR();
114   if ( anEngine == "-1" ) {
115     // Module doesn't have a CORBA engine and doesn't use
116     // a default one -> SALOMEDS persistence cannot be used
117     return false;
118   }
119
120   if ( anEngine.isEmpty() ) {
121     // Module use a default engine
122     //TODO: deside, if the below code has to be copyed in a light data model to avoid bulding of data tree twice
123     anEngine = SalomeApp_Application::defaultEngineIOR();
124   }
125
126   _PTR(Study)      aStudy ( aDoc->studyDS() ); // shared_ptr cannot be used here
127   _PTR(SComponent) aSComp ( aStudy->FindComponentID( std::string( anId.latin1() ) ) );
128
129   if ( aSComp ) {
130     _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() );
131     if ( aBuilder ) {
132       try {
133         aBuilder->LoadWith( aSComp, std::string( anEngine.latin1() ) );
134       }
135       catch( const SALOME::SALOME_Exception& ) {
136         // Oops, something went wrong while loading -> return an error
137         return false;
138       }
139
140       // Something has been read -> create data model tree
141       buildTree( aSComp, 0, aDoc );
142     }
143   } else {
144     // Don't return false here, for there might be no data
145     // for a given component in the study yet
146   }
147
148   emit opened(); //TODO: is it really needed? to be removed maybe...
149   return true;
150 }
151
152 //================================================================
153 // Function : save
154 /*! Purpose  : Emit saved()*/
155 //================================================================
156 bool SalomeApp_DataModel::save()
157 {
158   emit saved();
159   return true;
160 }
161
162 //================================================================
163 // Function : saveAs
164 /*! Purpose  : Emit saved() */
165 //================================================================
166 bool SalomeApp_DataModel::saveAs( const QString&, CAM_Study* )
167 {
168   emit saved();
169   return true;
170 }
171
172 //================================================================
173 // Function : close
174 /*! Purpose  : Emit closed()*/
175 //================================================================
176 bool SalomeApp_DataModel::close()
177 {
178   emit closed();
179   return true;
180 }
181
182 //================================================================
183 // Function : update
184 /*! Purpose  : Update application.*/
185 //================================================================
186 void SalomeApp_DataModel::update( SalomeApp_DataObject*, SalomeApp_Study* study )
187 {
188   SalomeApp_RootObject* studyRoot = 0;
189   _PTR(SObject) sobj;
190   SalomeApp_DataObject* modelRoot = dynamic_cast<SalomeApp_DataObject*>( root() );
191   if ( !modelRoot ){ // not yet connected to a study -> try using <study> argument
192     if ( !study )
193       study = dynamic_cast<SalomeApp_Study*>( getModule()->getApp()->activeStudy() );
194
195     if ( study ){
196       studyRoot = dynamic_cast<SalomeApp_RootObject*>( study->root() );
197       QString anId = getRootEntry( study );
198       if ( !anId.isEmpty() ){ // if nothing is published in the study for this module -> do nothing
199         _PTR(Study) aStudy ( study->studyDS() );
200         sobj = aStudy->FindComponentID( std::string( anId.latin1() ) );
201       }
202     }
203   }
204   else{
205     studyRoot = dynamic_cast<SalomeApp_RootObject*>( modelRoot->root() );
206     study = studyRoot->study(); // <study> value should not change here theoretically, but just to make sure
207     _PTR(Study) aStudy ( study->studyDS() );
208
209     // modelRoot->object() cannot be reused here: it is about to be deleted by buildTree() soon
210     sobj = aStudy->FindComponentID( std::string( modelRoot->entry().latin1() ) );
211   }
212   buildTree( sobj, studyRoot, study );
213 }
214
215 //================================================================
216 // Function : buildTree
217 /*! Purpose  : private method, build tree.*/
218 //================================================================
219 void SalomeApp_DataModel::buildTree( const _PTR(SObject)& obj,
220                                      SUIT_DataObject* parent,
221                                      SalomeApp_Study* study )
222 {
223   if ( !obj )
224     return;
225   //if ( !root() ){ // Build default SALOMEDS-based data object tree and insert it into study
226     SalomeApp_ModuleObject* aNewRoot = dynamic_cast<SalomeApp_ModuleObject*>( BuildTree( obj, parent, study ) );
227     if ( aNewRoot ){
228       aNewRoot->setDataModel( this );
229       setRoot( aNewRoot );
230     }
231     //}
232 }
233
234 //================================================================
235 // Function : getModule
236 /*! Purpose  : gets module*/
237 //================================================================
238
239 SalomeApp_Module* SalomeApp_DataModel::getModule() const
240 {
241   return dynamic_cast<SalomeApp_Module*>( module() );
242 }
243
244 //================================================================
245 // Function : getStudy
246 /*! Purpose  : gets study */
247 //================================================================
248 SalomeApp_Study* SalomeApp_DataModel::getStudy() const
249 {
250   SalomeApp_RootObject* aRoot = dynamic_cast<SalomeApp_RootObject*>( root()->root() );
251   if ( !aRoot )
252     return 0;
253   return aRoot->study();
254 }
255
256 //================================================================
257 // Function : getRootEntry
258 /*! Purpose  : returns study entry corresponding to this data model*/
259 //================================================================
260 QString SalomeApp_DataModel::getRootEntry( SalomeApp_Study* study ) const
261 {
262   QString anEntry;
263   if ( root() && root()->root() ) { // data model already in a study
264     SalomeApp_DataObject* anObj = dynamic_cast<SalomeApp_DataObject*>( root() );
265     if ( anObj )
266       anEntry = anObj->entry();
267   }
268   else if ( study && study->studyDS() ) { // this works even if <myRoot> is null
269     _PTR(SComponent) aSComp( study->studyDS()->FindComponent( module()->name() ) );
270     if ( aSComp )
271       anEntry = aSComp->GetID().c_str();
272   }
273   return anEntry;
274 }
275
276 //================================================================
277 // Function : isModified
278 /*! Purpose  : default implementation, always returns false so as not to mask study's isModified()*/
279 //================================================================
280 bool SalomeApp_DataModel::isModified() const
281 {
282   return false;
283 }
284
285 //================================================================
286 // Function : isSaved
287 /*! Purpose  : default implementation, always returns true so as not to mask study's isSaved()*/
288 //================================================================
289 bool SalomeApp_DataModel::isSaved() const
290 {
291   return true;
292 }
293
294 // BEGIN: methods to be used by CORBAless modules
295
296 //================================================================
297 // Function : GetListOfFiles
298 /*! Purpose  : to be used by CORBAless modules*/
299 //================================================================
300 std::vector<std::string> SalomeApp_DataModel::GetListOfFiles() const
301        //(const int theStudyId, const char* theComponentName) const
302 {
303   SUIT_Study* anActiveStudy = getModule()->getApp()->activeStudy();
304   if (anActiveStudy) {
305     int aStudyId = anActiveStudy->id();
306     SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
307     if (aDefaultEngine) {
308       return aDefaultEngine->GetListOfFiles(aStudyId, module()->name());
309     }
310   }
311
312   std::vector<std::string> aListOfFiles;
313   return aListOfFiles;
314 }
315
316 //================================================================
317 // Function : SetListOfFiles
318 /*! Purpose  : to be used by CORBAless modules*/
319 //================================================================
320 void SalomeApp_DataModel::SetListOfFiles (const std::vector<std::string> theListOfFiles)
321      //(const std::vector<std::string> theListOfFiles,
322      // const int                      theStudyId,
323      // const char*                    theComponentName)
324 {
325   SUIT_Study* anActiveStudy = getModule()->getApp()->activeStudy();
326   if (anActiveStudy) {
327     int aStudyId = anActiveStudy->id();
328     SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
329     if (aDefaultEngine) {
330       aDefaultEngine->SetListOfFiles(theListOfFiles, aStudyId, module()->name());
331     }
332   }
333 }
334
335 //================================================================
336 // Function : GetTmpDir
337 /*! Purpose  : Static method. To be used by CORBAless modules*/
338 //================================================================
339 std::string SalomeApp_DataModel::GetTmpDir (const char* theURL,
340                                             const bool  isMultiFile)
341 {
342   std::string anURLDir = SALOMEDS_Tool::GetDirFromPath(theURL);
343   std::string aTmpDir = isMultiFile ? anURLDir : SALOMEDS_Tool::GetTmpDir();
344   return aTmpDir;
345 }
346
347 //================================================================
348 // Function : RemoveTemporaryFiles
349 /*! Purpose  : to be used by CORBAless modules*/
350 //================================================================
351 void SalomeApp_DataModel::RemoveTemporaryFiles (const bool isMultiFile) const
352 {
353   if (isMultiFile)
354     return;
355
356   std::vector<std::string> aListOfFiles = GetListOfFiles();
357   if (aListOfFiles.size() > 0) {
358     std::string aTmpDir = aListOfFiles[0];
359
360     const int n = aListOfFiles.size() - 1;
361     SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
362     aSeq->length(n);
363     for (int i = 0; i < n; i++)
364       aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str());
365
366     SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
367   }
368 }
369
370 // END: methods to be used by CORBAless modules