1 // Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: SalomeApp_DataModel.cxx
24 // Created: 10/25/2004 10:36:06 AM
25 // Author: Sergey LITONIN
27 #include "SalomeApp_DataModel.h"
28 #include "SalomeApp_Study.h"
29 #include "SalomeApp_DataObject.h"
30 #include "SalomeApp_Module.h"
31 #include "SalomeApp_Application.h"
33 #include <CAM_DataObject.h>
35 #include <SUIT_TreeSync.h>
36 #include <SUIT_DataObjectIterator.h>
38 #include <SALOMEconfig.h>
39 #include CORBA_SERVER_HEADER(SALOME_Exception)
41 typedef _PTR(SObject) kerPtr;
42 typedef SUIT_DataObject* suitPtr;
45 \class SalomeApp_DataModelSync
46 Auxiliary class for synchronizing tree of kernel objects and SUIT_DataObjects
48 class SalomeApp_DataModelSync
51 SalomeApp_DataModelSync( _PTR( Study ), SUIT_DataObject* );
53 bool isEqual( const kerPtr&, const suitPtr& ) const;
54 kerPtr nullSrc() const;
55 suitPtr nullTrg() const;
56 suitPtr createItem( const kerPtr&, const suitPtr&, const suitPtr& ) const;
57 void updateItem( const kerPtr&, const suitPtr& ) const;
58 void deleteItemWithChildren( const suitPtr& ) const;
59 QList<kerPtr> children( const kerPtr& ) const;
60 QList<suitPtr> children( const suitPtr& ) const;
61 suitPtr parent( const suitPtr& ) const;
64 bool isCorrect( const kerPtr& ) const;
67 _PTR( Study ) myStudy;
68 SUIT_DataObject* myRoot;
74 SalomeApp_DataModelSync::SalomeApp_DataModelSync( _PTR( Study ) aStudy, SUIT_DataObject* aRoot )
81 \return true if kernel object is correct (has non empty name or is reference)
83 bool SalomeApp_DataModelSync::isCorrect( const kerPtr& so ) const
85 #ifdef WITH_SALOMEDS_OBSERVER
86 // with GUI observers this function is not needed anymore
90 QString name = so->GetName().c_str();
91 _PTR( GenericAttribute ) anAttr;
93 if ( so->FindAttribute(anAttr, "AttributeDrawable") )
95 _PTR(AttributeDrawable) aAttrDraw = anAttr;
96 isDraw = aAttrDraw->IsDrawable();
98 bool res = so && ( so->GetName().size() || so->ReferencedObject( refObj ) ) && isDraw;
103 Creates SUIT object by KERNEL object
104 \param so - corresponding KERNEL object
105 \param parent - parent for SUIT object
106 \param after - previous sibling for SUIT object
107 \param prepend - SUIT object must be added to start of children list
109 suitPtr SalomeApp_DataModelSync::createItem( const kerPtr& so,
110 const suitPtr& parent,
111 const suitPtr& after ) const
113 if( !isCorrect( so ) )
116 _PTR(SComponent) aSComp( so );
117 suitPtr nitem = aSComp ? new SalomeApp_ModuleObject( aSComp, 0 ) :
118 new SalomeApp_DataObject( so, 0 );
121 int pos = after ? parent->childPos( after ) : 0;
122 parent->insertChild( nitem, pos+1 );
125 myRoot->appendChild( nitem );
131 Deletes object with all children
132 \param p - SUIT object
134 void SalomeApp_DataModelSync::deleteItemWithChildren( const suitPtr& p ) const
141 DataObjectList::const_iterator anIt = ch.begin(), aLast = ch.end();
142 for( ; anIt!=aLast; anIt++ )
143 deleteItemWithChildren( *anIt );
148 \return true if objects correspond each other at all
149 \param p - kernel object
150 \param q - suit object
152 bool SalomeApp_DataModelSync::isEqual( const kerPtr& p, const suitPtr& q ) const
154 LightApp_ModuleObject* lobj = dynamic_cast<LightApp_ModuleObject*>( q );
155 SalomeApp_DataObject* sobj = dynamic_cast<SalomeApp_DataObject*>( q );
156 _PTR( SComponent ) aComp( p );
157 bool res = ( !p && !q ) ||
158 ( lobj && !sobj && aComp ) ||
159 ( sobj && isCorrect( p ) && p->GetID().c_str()==sobj->entry() );
164 \return null kernel object
166 kerPtr SalomeApp_DataModelSync::nullSrc() const
172 \return null suit object
174 suitPtr SalomeApp_DataModelSync::nullTrg() const
180 Fills list with children of kernel object
181 \param obj - kernel object
182 \param ch - list to be filled
184 QList<kerPtr> SalomeApp_DataModelSync::children( const kerPtr& obj ) const
188 _PTR( GenericAttribute ) anAttr;
189 bool expandable = true;
190 if ( obj && obj->FindAttribute( anAttr, "AttributeExpandable" ) ) {
191 _PTR(AttributeExpandable) aAttrExp = anAttr;
192 expandable = aAttrExp->IsExpandable();
197 _PTR(UseCaseBuilder) aUseCaseBuilder = myStudy->GetUseCaseBuilder();
198 if (aUseCaseBuilder->HasChildren(obj)) {
199 _PTR(UseCaseIterator) it ( aUseCaseBuilder->GetUseCaseIterator( obj ) );
200 for ( ; it->More(); it->Next() )
201 ch.append( it->Value() );
204 _PTR(ChildIterator) it ( myStudy->NewChildIterator( obj ) );
205 for ( ; it->More(); it->Next() )
206 ch.append( it->Value() );
214 Fills list with children of SUIT object
215 \param p - SUIT object
216 \param ch - list to be filled
218 QList<suitPtr> SalomeApp_DataModelSync::children( const suitPtr& p ) const
227 \return parent of SUIT object
228 \param p - SUIT object
230 suitPtr SalomeApp_DataModelSync::parent( const suitPtr& p ) const
232 return p ? p->parent(): 0;
237 \param p - SUIT object
239 void SalomeApp_DataModelSync::updateItem( const kerPtr& obj, const suitPtr& ) const
244 Auxiliary function, shows SUIT tree
246 void showTree( SUIT_DataObject* root )
248 qDebug( root ? "<tree>" : "<empty tree>" );
252 SUIT_DataObjectIterator it( root, SUIT_DataObjectIterator::DepthLeft );
253 for( ; it.current(); ++it )
255 QString marg; marg.fill( ' ', 3*it.depth() );
256 QString nnn = "%1 '%2'";
257 qDebug( nnn.arg( marg ).arg( it.current()->name() ).toUtf8() );
264 SalomeApp_DataModel::SalomeApp_DataModel( CAM_Module* theModule )
265 : LightApp_DataModel( theModule )
272 SalomeApp_DataModel::~SalomeApp_DataModel()
279 bool SalomeApp_DataModel::open( const QString& name, CAM_Study* study, QStringList )
281 SalomeApp_Study* aDoc = dynamic_cast<SalomeApp_Study*>( study );
285 QString anId = getRootEntry( aDoc );
286 if ( anId.isEmpty() )
287 return true; // Probably nothing to load
289 _PTR(SComponent) aSComp ( SalomeApp_Application::getStudy()->FindComponentID( std::string( anId.toUtf8() ) ) );
291 updateTree( aSComp, aDoc );
293 QStringList listOfFiles;
294 LightApp_DataModel::open(name, study, listOfFiles);
301 bool SalomeApp_DataModel::create( CAM_Study* theStudy )
303 update(NULL, (LightApp_Study*)theStudy);
310 void SalomeApp_DataModel::update( LightApp_DataObject*, LightApp_Study* study )
312 SalomeApp_Study* aSStudy = dynamic_cast<SalomeApp_Study*>(study);
313 LightApp_RootObject* studyRoot = 0;
314 _PTR(SComponent) sobj;
315 SalomeApp_DataObject* modelRoot = dynamic_cast<SalomeApp_DataObject*>( root() );
316 if ( !modelRoot ){ // not yet connected to a study -> try using <study> argument
318 aSStudy = dynamic_cast<SalomeApp_Study*>( getModule()->getApp()->activeStudy() );
320 studyRoot = dynamic_cast<LightApp_RootObject*>( aSStudy->root() );
321 QString anId = getRootEntry( aSStudy );
322 if ( !anId.isEmpty() ){ // if nothing is published in the study for this module -> do nothing
323 sobj = SalomeApp_Application::getStudy()->FindComponentID( std::string( anId.toUtf8() ) );
328 studyRoot = dynamic_cast<LightApp_RootObject*>( modelRoot->root() );
330 aSStudy = dynamic_cast<SalomeApp_Study*>( studyRoot->study() ); // <study> value should not change here theoretically, but just to make sure
332 // modelRoot->object() cannot be reused here: it is about to be deleted by buildTree() soon
333 sobj = SalomeApp_Application::getStudy()->FindComponentID( std::string( modelRoot->entry().toUtf8() ) );
337 if ( sobj && aSStudy )
338 updateTree( sobj, aSStudy );
342 Synchronizes kernel tree and suit data tree starting from component 'sobj'
344 SUIT_DataObject* SalomeApp_DataModel::synchronize( const _PTR( SComponent )& sobj, SalomeApp_Study* study )
346 if( !study || !study->root() || !sobj )
349 DataObjectList ch; study->root()->children( ch );
350 DataObjectList::const_iterator anIt = ch.begin(), aLast = ch.end();
351 SUIT_DataObject* suitObj = 0;
352 for( ; anIt!=aLast; anIt++ )
354 LightApp_DataObject* dobj = dynamic_cast<LightApp_DataObject*>( *anIt );
355 if( dobj && dobj->name() == sobj->GetName().c_str() )
362 #ifdef WITH_SALOMEDS_OBSERVER
363 SalomeApp_RootObject* root=dynamic_cast<SalomeApp_RootObject*>(study->root());
364 if(!(root->toSynchronize()))
368 SalomeApp_DataModelSync sync( study->studyDS(), study->root() );
370 if( !suitObj || dynamic_cast<SalomeApp_DataObject*>( suitObj ) )
371 suitObj= ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, suitObj, sync );
381 void SalomeApp_DataModel::updateTree( const _PTR( SComponent )& comp, SalomeApp_Study* study )
383 SalomeApp_ModuleObject* aNewRoot = dynamic_cast<SalomeApp_ModuleObject*>( synchronize( comp, study ) );
386 aNewRoot->setDataModel( this );
394 SalomeApp_Module* SalomeApp_DataModel::getModule() const
396 return dynamic_cast<SalomeApp_Module*>( module() );
402 SalomeApp_Study* SalomeApp_DataModel::getStudy() const
404 if(!root()) return 0;
405 LightApp_RootObject* aRoot = dynamic_cast<LightApp_RootObject*>( root()->root() );
408 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( aRoot->study() );
415 \return study entry corresponding to this data model
417 QString SalomeApp_DataModel::getRootEntry( SalomeApp_Study* study ) const
420 if ( root() && root()->root() ) { // data model already in a study
421 SalomeApp_DataObject* anObj = dynamic_cast<SalomeApp_DataObject*>( root() );
423 anEntry = anObj->entry();
425 else if ( study && study->studyDS() ) { // this works even if <myRoot> is null
426 _PTR(SComponent) aSComp( study->studyDS()->FindComponent( module()->name().toStdString() ) );
428 anEntry = aSComp->GetID().c_str();