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