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