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