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