Salome HOME
Merge from OCC_development_generic_2006
[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_DataObject.h"
9 #include "SalomeApp_Module.h"
10 #include "SalomeApp_Application.h"
11 #include "SalomeApp_Engine_i.hxx"
12
13 #include "LightApp_RootObject.h"
14
15 #include <CAM_DataObject.h>
16
17 #include <SUIT_Application.h>
18 #include <SUIT_ResourceMgr.h>
19 #include <SUIT_Session.h>
20 #include <SUIT_TreeSync.h>
21 #include <SUIT_DataObjectIterator.h>
22
23 #include "SALOMEDS_Tool.hxx"
24
25 #include <SALOMEconfig.h>
26 #include CORBA_SERVER_HEADER(SALOME_Exception)
27
28 //=======================================================================
29 // name    : SalomeApp_DataModelSync
30 /*!Purpose : Auxiliary class for synchronizing tree of kernel objects and SUIT_DataObjects  */
31 //=======================================================================
32
33 typedef _PTR(SObject)     kerPtr;
34 typedef SUIT_DataObject*  suitPtr;
35
36 class SalomeApp_DataModelSync
37 {
38 public:
39   SalomeApp_DataModelSync( _PTR( Study ), SUIT_DataObject* );
40
41   suitPtr  createItem( const kerPtr&, const suitPtr&, const suitPtr&, const bool ) const;
42   void     deleteItemWithChildren( const suitPtr& ) const;
43   bool     isEqual( const kerPtr&, const suitPtr& ) const;
44   kerPtr   nullSrc() const;
45   suitPtr  nullTrg() const;
46   void     children( const kerPtr&, QValueList<kerPtr>& ) const;
47   void     children( const suitPtr&, QValueList<suitPtr>& ) const;
48   suitPtr  parent( const suitPtr& ) const;
49   bool     isCorrect( const kerPtr& ) const;
50   void     updateItem( const suitPtr& ) const;
51
52 private:
53   _PTR( Study )     myStudy;
54   SUIT_DataObject*  myRoot;
55 };
56
57
58 SalomeApp_DataModelSync::SalomeApp_DataModelSync( _PTR( Study ) aStudy, SUIT_DataObject* aRoot )
59 : myStudy( aStudy ),
60   myRoot( aRoot )
61 {
62 }
63
64 bool SalomeApp_DataModelSync::isCorrect( const kerPtr& so ) const
65 {
66   kerPtr refObj;
67   QString name = so->GetName();
68   bool res = so && ( so->GetName().size() || so->ReferencedObject( refObj ) );
69   return res;
70 }
71
72 suitPtr SalomeApp_DataModelSync::createItem( const kerPtr& so,
73                                              const suitPtr& parent,
74                                              const suitPtr& after,
75                                              const bool asFirst ) const
76 {
77   if( !isCorrect( so ) )
78     return 0;
79
80   _PTR(SComponent) aSComp( so );
81   suitPtr nitem = aSComp ? new SalomeApp_ModuleObject( aSComp, 0 ) :
82                            new SalomeApp_DataObject( so, 0 );
83   if( parent )
84     if( after )
85     {
86       DataObjectList ch;
87       parent->children( ch );
88       int pos = ch.find( after );
89       if( pos>=0 )
90         parent->insertChild( nitem, pos+1 );
91       else
92         parent->appendChild( nitem );
93     }
94     else if( asFirst )
95       parent->insertChild( nitem, 0 );
96     else
97       parent->appendChild( nitem );
98   else if( myRoot )
99     myRoot->appendChild( nitem );
100   return nitem;
101 }
102
103 void SalomeApp_DataModelSync::deleteItemWithChildren( const suitPtr& p ) const
104 {
105   if( !p )
106     return;
107
108   DataObjectList ch;
109   p->children( ch );
110   DataObjectList::const_iterator anIt = ch.begin(), aLast = ch.end();
111   for( ; anIt!=aLast; anIt++ )
112     deleteItemWithChildren( *anIt );
113   delete p;
114 }
115
116 bool SalomeApp_DataModelSync::isEqual( const kerPtr& p, const suitPtr& q ) const
117 {
118   LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( q );
119   return ( !p && !q ) || ( obj && isCorrect( p ) && p->GetID()==obj->entry() );
120 }
121
122 kerPtr SalomeApp_DataModelSync::nullSrc() const
123 {
124   return kerPtr();
125 }
126
127 suitPtr SalomeApp_DataModelSync::nullTrg() const
128 {
129   return suitPtr( 0 );
130 }
131
132 void SalomeApp_DataModelSync::children( const kerPtr& obj, QValueList<kerPtr>& ch ) const
133 {
134   ch.clear();
135   _PTR(ChildIterator) it ( myStudy->NewChildIterator( obj ) );
136   for( ; it->More(); it->Next() )
137     ch.append( it->Value() );
138 }
139
140 void SalomeApp_DataModelSync::children( const suitPtr& p, QValueList<suitPtr>& ch ) const
141 {
142   DataObjectList l;
143   if( p )
144   {
145     p->children( l );
146     ch.clear();
147     for( SUIT_DataObject* o = l.first(); o; o = l.next() )
148       ch.append( o );
149   }
150 }
151
152 suitPtr SalomeApp_DataModelSync::parent( const suitPtr& p ) const
153 {
154   return p ? p->parent(): 0;
155 }
156
157 void SalomeApp_DataModelSync::updateItem( const suitPtr& ) const
158 {
159 }
160
161 void showTree( SUIT_DataObject* root )
162 {
163   qDebug( root ? "<tree>" : "<empty tree>" );
164   if( !root )
165     return;
166
167   SUIT_DataObjectIterator it( root, SUIT_DataObjectIterator::DepthLeft );
168   for( ; it.current(); ++it )
169   {
170     QString marg; marg.fill( ' ', 3*it.depth() );
171     QString nnn = "%1 '%2'";
172     qDebug( nnn.arg( marg ).arg( it.current()->name() ) );
173   }
174 }
175
176 //=======================================================================
177 // name    : SalomeApp_DataModel::SalomeApp_DataModel
178 /*!Purpose : Constructor*/
179 //=======================================================================
180 SalomeApp_DataModel::SalomeApp_DataModel( CAM_Module* theModule )
181 : LightApp_DataModel( theModule )
182 {
183 }
184
185 //=======================================================================
186 // name    : SalomeApp_DataModel::~SalomeApp_DataModel
187 /*! Purpose : Destructor*/
188 //=======================================================================
189 SalomeApp_DataModel::~SalomeApp_DataModel()
190 {
191 }
192
193 //================================================================
194 // Function : open
195 /*! Purpose  : Open data model*/
196 //================================================================
197 bool SalomeApp_DataModel::open( const QString& name, CAM_Study* study, QStringList )
198 {
199   SalomeApp_Study* aDoc = dynamic_cast<SalomeApp_Study*>( study );
200   if ( !aDoc )
201     return false;
202
203   QString anId = getRootEntry( aDoc );
204   if ( anId.isEmpty() )
205     return true; // Probably nothing to load
206
207   _PTR(Study)      aStudy ( aDoc->studyDS() ); // shared_ptr cannot be used here
208   _PTR(SComponent) aSComp ( aStudy->FindComponentID( std::string( anId.latin1() ) ) );
209   if ( aSComp )
210     updateTree( aSComp, aDoc );
211
212   QStringList listOfFiles;
213   LightApp_DataModel::open(name, study, listOfFiles);
214   return true;
215 }
216
217 //================================================================
218 // Function : create
219 /*! Purpose  : Create data model*/
220 //================================================================
221 bool SalomeApp_DataModel::create( CAM_Study* theStudy )
222 {
223   update(NULL, (LightApp_Study*)theStudy);
224   return true;
225 }
226
227 //================================================================
228 // Function : update
229 /*! Purpose  : Update application.*/
230 //================================================================
231 void SalomeApp_DataModel::update( LightApp_DataObject*, LightApp_Study* study )
232 {
233   SalomeApp_Study* aSStudy = dynamic_cast<SalomeApp_Study*>(study);
234   LightApp_RootObject* studyRoot = 0;
235   _PTR(SComponent) sobj;
236   SalomeApp_DataObject* modelRoot = dynamic_cast<SalomeApp_DataObject*>( root() );
237   if ( !modelRoot ){ // not yet connected to a study -> try using <study> argument
238     if ( !aSStudy )
239       aSStudy = dynamic_cast<SalomeApp_Study*>( getModule()->getApp()->activeStudy() );
240     if ( aSStudy ){
241       studyRoot = dynamic_cast<LightApp_RootObject*>( aSStudy->root() );
242       QString anId = getRootEntry( aSStudy );
243       if ( !anId.isEmpty() ){ // if nothing is published in the study for this module -> do nothing
244         _PTR(Study) aStudy ( aSStudy->studyDS() );
245         sobj = aStudy->FindComponentID( std::string( anId.latin1() ) );
246       }
247     }
248   }
249   else{
250     studyRoot = dynamic_cast<LightApp_RootObject*>( modelRoot->root() );
251     if ( studyRoot ) {
252       aSStudy = dynamic_cast<SalomeApp_Study*>( studyRoot->study() ); // <study> value should not change here theoretically, but just to make sure
253       if ( aSStudy ) {
254         _PTR(Study) aStudy ( aSStudy->studyDS() );
255         // modelRoot->object() cannot be reused here: it is about to be deleted by buildTree() soon
256         sobj = aStudy->FindComponentID( std::string( modelRoot->entry().latin1() ) );
257       }
258     }
259   }
260   if ( sobj && aSStudy )
261     updateTree( sobj, aSStudy );
262 }
263
264 //================================================================
265 // Function : synchronize
266 /*! Purpose  : synchronizes kernel tree and suit data tree starting from component 'sobj' */
267 //================================================================
268 SUIT_DataObject* SalomeApp_DataModel::synchronize( const _PTR( SComponent )& sobj, SalomeApp_Study* study )
269 {
270   if( !study || !study->root() || !sobj )
271     return 0;
272
273   DataObjectList ch; study->root()->children( ch );
274   DataObjectList::const_iterator anIt = ch.begin(), aLast = ch.end();
275   SalomeApp_DataObject* suitObj = 0;
276   for( ; anIt!=aLast; anIt++ )
277   {
278     SalomeApp_DataObject* dobj = dynamic_cast<SalomeApp_DataObject*>( *anIt );
279     if( dobj && dobj->name()==sobj->GetName().c_str() )
280     {
281       suitObj = dobj;
282       break;
283     }
284   }
285
286   SalomeApp_DataModelSync sync( study->studyDS(), study->root() );
287
288   //  QString srcName = sobj ? sobj->GetName().c_str() : "";
289   //  QString trgName = ( suitObj && !suitObj->name().isNull() ) ? suitObj->name() : "";
290   //  printf( "--- SalomeApp_DataModel::syncronize() calls synchronize()_1: src = %s, trg = %s ---\n",  srcName.latin1(), trgName.latin1() );
291
292   SUIT_DataObject* o = ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, suitObj, sync );
293 //  showTree( o );
294   return o;
295 }
296
297 //================================================================
298 // Function : synchronize
299 /*! Purpose  : synchronizes kernel tree and suit data tree starting from 'sobj' and 'obj' correspondly */
300 //================================================================
301 SUIT_DataObject* SalomeApp_DataModel::synchronize( const _PTR( SObject )& sobj, SUIT_DataObject* obj,
302                                                    SalomeApp_Study* study )
303 {
304   if( !study )
305     return 0;
306   SalomeApp_DataModelSync sync( study->studyDS(), study->root() );
307
308   //  QString srcName = sobj ? sobj->GetName().c_str() : "";
309   //  QString trgName = ( obj && !obj->name().isNull() ) ? obj->name() : "";
310   //  printf( "--- SalomeApp_DataModel::syncronize() calls synchronize()_2: src = s, trg = %s ---\n",  srcName.latin1(), trgName.latin1() );
311
312   return ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, obj, sync );
313 }
314
315 //================================================================
316 // Function : updateTree
317 /*! Purpose  : updates tree.*/
318 //================================================================
319 void SalomeApp_DataModel::updateTree( const _PTR( SComponent )& comp, SalomeApp_Study* study )
320 {
321   SalomeApp_ModuleObject* aNewRoot = dynamic_cast<SalomeApp_ModuleObject*>( synchronize( comp, study ) );
322   if( aNewRoot )
323   {
324     aNewRoot->setDataModel( this );
325     setRoot( aNewRoot );
326   }
327 }
328
329 //================================================================
330 // Function : getModule
331 /*! Purpose  : gets module*/
332 //================================================================
333
334 SalomeApp_Module* SalomeApp_DataModel::getModule() const
335 {
336   return dynamic_cast<SalomeApp_Module*>( module() );
337 }
338
339 //================================================================
340 // Function : getStudy
341 /*! Purpose  : gets study */
342 //================================================================
343 SalomeApp_Study* SalomeApp_DataModel::getStudy() const
344 {
345   if(!root()) return 0;
346   LightApp_RootObject* aRoot = dynamic_cast<LightApp_RootObject*>( root()->root() );
347   if ( !aRoot )
348     return 0;
349   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( aRoot->study() );
350   if ( !aStudy )
351     return 0;
352   return aStudy;
353 }
354
355 //================================================================
356 // Function : getRootEntry
357 /*! Purpose  : returns study entry corresponding to this data model*/
358 //================================================================
359 QString SalomeApp_DataModel::getRootEntry( SalomeApp_Study* study ) const
360 {
361   QString anEntry;
362   if ( root() && root()->root() ) { // data model already in a study
363     SalomeApp_DataObject* anObj = dynamic_cast<SalomeApp_DataObject*>( root() );
364     if ( anObj )
365       anEntry = anObj->entry();
366   }
367   else if ( study && study->studyDS() ) { // this works even if <myRoot> is null
368     _PTR(SComponent) aSComp( study->studyDS()->FindComponent( module()->name() ) );
369     if ( aSComp )
370       anEntry = aSComp->GetID().c_str();
371   }
372   return anEntry;
373 }