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