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