Salome HOME
Unicode support: correct handling of unicode on GUI level
[modules/gui.git] / src / SalomeApp / SalomeApp_DataModel.cxx
index 2a043ff1975bb029a40055b9f15799fbb81730ed..b2adf0da81555ebaa5d3f3cc6df7ebd168007c6f 100644 (file)
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
 // File:      SalomeApp_DataModel.cxx
 // Created:   10/25/2004 10:36:06 AM
 // Author:    Sergey LITONIN
-// Copyright (C) CEA 2004
 
 #include "SalomeApp_DataModel.h"
 #include "SalomeApp_Study.h"
 #include "SalomeApp_DataObject.h"
 #include "SalomeApp_Module.h"
 #include "SalomeApp_Application.h"
-#include "SalomeApp_Engine_i.hxx"
-
-#include "LightApp_RootObject.h"
 
 #include <CAM_DataObject.h>
 
-#include <SUIT_Application.h>
-#include <SUIT_ResourceMgr.h>
-#include <SUIT_Session.h>
 #include <SUIT_TreeSync.h>
 #include <SUIT_DataObjectIterator.h>
 
-#include "SALOMEDS_Tool.hxx"
-
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SALOME_Exception)
 
-//=======================================================================
-// name    : SalomeApp_DataModelSync
-/*!Purpose : Auxiliary class for synchronizing tree of kernel objects and SUIT_DataObjects  */
-//=======================================================================
-
 typedef _PTR(SObject)     kerPtr;
 typedef SUIT_DataObject*  suitPtr;
 
+/*!
+  \class SalomeApp_DataModelSync
+  Auxiliary class for synchronizing tree of kernel objects and SUIT_DataObjects
+*/
 class SalomeApp_DataModelSync
 {
 public:
   SalomeApp_DataModelSync( _PTR( Study ), SUIT_DataObject* );
 
-  suitPtr  createItem( const kerPtr&, const suitPtr&, const suitPtr&, const bool ) const;
-  void     deleteItemWithChildren( const suitPtr& ) const;
-  bool     isEqual( const kerPtr&, const suitPtr& ) const;
-  kerPtr   nullSrc() const;
-  suitPtr  nullTrg() const;
-  void     children( const kerPtr&, QValueList<kerPtr>& ) const;
-  void     children( const suitPtr&, QValueList<suitPtr>& ) const;
-  suitPtr  parent( const suitPtr& ) const;
-  bool     isCorrect( const kerPtr& ) const;
-  void     updateItem( const suitPtr& ) const;
+  bool           isEqual( const kerPtr&, const suitPtr& ) const;
+  kerPtr         nullSrc() const;
+  suitPtr        nullTrg() const;
+  suitPtr        createItem( const kerPtr&, const suitPtr&, const suitPtr& ) const;
+  void           updateItem( const kerPtr&, const suitPtr& ) const;
+  void           deleteItemWithChildren( const suitPtr& ) const;
+  QList<kerPtr>  children( const kerPtr& ) const;
+  QList<suitPtr> children( const suitPtr& ) const;
+  suitPtr        parent( const suitPtr& ) const;
+
+private:
+  bool           isCorrect( const kerPtr& ) const;
 
 private:
   _PTR( Study )     myStudy;
   SUIT_DataObject*  myRoot;
 };
 
-
+/*!
+  Constructor
+*/
 SalomeApp_DataModelSync::SalomeApp_DataModelSync( _PTR( Study ) aStudy, SUIT_DataObject* aRoot )
 : myStudy( aStudy ),
   myRoot( aRoot )
 {
 }
 
+/*!
+  \return true if kernel object is correct (has non empty name or is reference)
+*/
 bool SalomeApp_DataModelSync::isCorrect( const kerPtr& so ) const
 {
+#ifdef WITH_SALOMEDS_OBSERVER
+  // with GUI observers this function is not needed anymore
+  return true;
+#endif
   kerPtr refObj;
-  QString name = so->GetName();
-  bool res = so && ( so->GetName().size() || so->ReferencedObject( refObj ) );
+  QString name = so->GetName().c_str();
+  _PTR( GenericAttribute ) anAttr;
+  bool isDraw = true;
+  if ( so->FindAttribute(anAttr, "AttributeDrawable") ) 
+  {
+    _PTR(AttributeDrawable) aAttrDraw = anAttr;
+    isDraw = aAttrDraw->IsDrawable(); 
+  }
+  bool res = so && ( so->GetName().size() || so->ReferencedObject( refObj ) ) && isDraw;  
   return res;
 }
 
+/*!
+  Creates SUIT object by KERNEL object
+  \param so - corresponding KERNEL object
+  \param parent - parent for SUIT object
+  \param after - previous sibling for SUIT object
+  \param prepend - SUIT object must be added to start of children list
+*/
 suitPtr SalomeApp_DataModelSync::createItem( const kerPtr& so,
-                                            const suitPtr& parent,
-                                            const suitPtr& after,
-                                            const bool prepend ) const
+                                             const suitPtr& parent,
+                                             const suitPtr& after ) const
 {
   if( !isCorrect( so ) )
     return 0;
@@ -80,26 +116,21 @@ suitPtr SalomeApp_DataModelSync::createItem( const kerPtr& so,
   _PTR(SComponent) aSComp( so );
   suitPtr nitem = aSComp ? new SalomeApp_ModuleObject( aSComp, 0 ) :
                            new SalomeApp_DataObject( so, 0 );
-  if( parent )
-    if( after )
-    {
-      DataObjectList ch;
-      parent->children( ch );
-      int pos = ch.find( after );
-      if( pos>=0 )
-       parent->insertChild( nitem, pos+1 );
-      else
-       parent->appendChild( nitem );
-    }
-    else if( prepend )
-      parent->insertChild( nitem, 0 );
-    else // append
-      parent->appendChild( nitem );
-  else if( myRoot )
+
+  if( parent ) {
+    int pos = after ? parent->childPos( after ) : 0;
+    parent->insertChild( nitem, pos+1 );
+  }
+  else if( myRoot ) {
     myRoot->appendChild( nitem );
+  }
   return nitem;
 }
 
+/*!
+  Deletes object with all children
+  \param p - SUIT object
+*/
 void SalomeApp_DataModelSync::deleteItemWithChildren( const suitPtr& p ) const
 {
   if( !p )
@@ -113,51 +144,105 @@ void SalomeApp_DataModelSync::deleteItemWithChildren( const suitPtr& p ) const
   delete p;
 }
 
+/*!
+  \return true if objects correspond each other at all
+  \param p - kernel object
+  \param q - suit object
+*/
 bool SalomeApp_DataModelSync::isEqual( const kerPtr& p, const suitPtr& q ) const
 {
-  LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( q );
-  return ( !p && !q ) || ( obj && isCorrect( p ) && p->GetID()==obj->entry() );
+  LightApp_ModuleObject* lobj = dynamic_cast<LightApp_ModuleObject*>( q );
+  SalomeApp_DataObject* sobj = dynamic_cast<SalomeApp_DataObject*>( q );
+  _PTR( SComponent ) aComp( p );
+  bool res = ( !p && !q ) ||
+             ( lobj && !sobj && aComp ) ||
+             ( sobj && isCorrect( p ) && p->GetID().c_str()==sobj->entry() );
+  return res;
 }
 
+/*!
+  \return null kernel object
+*/
 kerPtr SalomeApp_DataModelSync::nullSrc() const
 {
   return kerPtr();
 }
 
+/*!
+  \return null suit object
+*/
 suitPtr SalomeApp_DataModelSync::nullTrg() const
 {
-  return suitPtr( 0 );
+  return 0;
 }
 
-void SalomeApp_DataModelSync::children( const kerPtr& obj, QValueList<kerPtr>& ch ) const
+/*!
+  Fills list with children of kernel object
+  \param obj - kernel object
+  \param ch - list to be filled
+*/
+QList<kerPtr> SalomeApp_DataModelSync::children( const kerPtr& obj ) const
 {
-  ch.clear();
-  _PTR(ChildIterator) it ( myStudy->NewChildIterator( obj ) );
-  for( ; it->More(); it->Next() )
-    ch.append( it->Value() );
+  QList<kerPtr> ch;
+
+  _PTR( GenericAttribute ) anAttr;
+  bool expandable = true;
+  if ( obj && obj->FindAttribute( anAttr, "AttributeExpandable" ) ) {
+    _PTR(AttributeExpandable) aAttrExp = anAttr;
+    expandable = aAttrExp->IsExpandable();
+  }
+
+  if ( expandable ) {
+    // tmp??
+    _PTR(UseCaseBuilder) aUseCaseBuilder = myStudy->GetUseCaseBuilder();
+    if (aUseCaseBuilder->HasChildren(obj)) {
+      _PTR(UseCaseIterator) it ( aUseCaseBuilder->GetUseCaseIterator( obj ) );
+      for ( ; it->More(); it->Next() )
+        ch.append( it->Value() );
+    }
+    else {
+      _PTR(ChildIterator) it ( myStudy->NewChildIterator( obj ) );
+      for ( ; it->More(); it->Next() )
+        ch.append( it->Value() );
+    }
+  }
+
+  return ch;
 }
 
-void SalomeApp_DataModelSync::children( const suitPtr& p, QValueList<suitPtr>& ch ) const
+/*!
+  Fills list with children of SUIT object
+  \param p - SUIT object
+  \param ch - list to be filled
+*/
+QList<suitPtr> SalomeApp_DataModelSync::children( const suitPtr& p ) const
 {
-  DataObjectList l;
-  if( p )
-  {
-    p->children( l );
-    ch.clear();
-    for( SUIT_DataObject* o = l.first(); o; o = l.next() )
-      ch.append( o );
-  }
+  QList<suitPtr> ch;
+  if ( p )
+    ch = p->children();
+  return ch;
 }
 
+/*!
+  \return parent of SUIT object
+  \param p - SUIT object
+*/
 suitPtr SalomeApp_DataModelSync::parent( const suitPtr& p ) const
 {
   return p ? p->parent(): 0;
 }
 
-void SalomeApp_DataModelSync::updateItem( const suitPtr& ) const
+/*!
+  Updates SUIT object
+  \param p - SUIT object
+*/
+void SalomeApp_DataModelSync::updateItem( const kerPtr& obj, const suitPtr& ) const
 {
 }
 
+/*!
+  Auxiliary function, shows SUIT tree
+*/
 void showTree( SUIT_DataObject* root )
 {
   qDebug( root ? "<tree>" : "<empty tree>" );
@@ -169,31 +254,28 @@ void showTree( SUIT_DataObject* root )
   {
     QString marg; marg.fill( ' ', 3*it.depth() );
     QString nnn = "%1 '%2'";
-    qDebug( nnn.arg( marg ).arg( it.current()->name() ) );
+    qDebug( nnn.arg( marg ).arg( it.current()->name() ).toUtf8() );
   }
 }
 
-//=======================================================================
-// name    : SalomeApp_DataModel::SalomeApp_DataModel
-/*!Purpose : Constructor*/
-//=======================================================================
+/*!
+  Constructor
+*/
 SalomeApp_DataModel::SalomeApp_DataModel( CAM_Module* theModule )
 : LightApp_DataModel( theModule )
 {
 }
 
-//=======================================================================
-// name    : SalomeApp_DataModel::~SalomeApp_DataModel
-/*! Purpose : Destructor*/
-//=======================================================================
+/*!
+  Destructor
+*/
 SalomeApp_DataModel::~SalomeApp_DataModel()
 {
 }
 
-//================================================================
-// Function : open
-/*! Purpose  : Open data model*/
-//================================================================
+/*!
+  Opens data model
+*/
 bool SalomeApp_DataModel::open( const QString& name, CAM_Study* study, QStringList )
 {
   SalomeApp_Study* aDoc = dynamic_cast<SalomeApp_Study*>( study );
@@ -204,8 +286,7 @@ bool SalomeApp_DataModel::open( const QString& name, CAM_Study* study, QStringLi
   if ( anId.isEmpty() )
     return true; // Probably nothing to load
 
-  _PTR(Study)      aStudy ( aDoc->studyDS() ); // shared_ptr cannot be used here
-  _PTR(SComponent) aSComp ( aStudy->FindComponentID( std::string( anId.latin1() ) ) );
+  _PTR(SComponent) aSComp ( SalomeApp_Application::getStudy()->FindComponentID( std::string( anId.toUtf8() ) ) );
   if ( aSComp )
     updateTree( aSComp, aDoc );
 
@@ -214,20 +295,18 @@ bool SalomeApp_DataModel::open( const QString& name, CAM_Study* study, QStringLi
   return true;
 }
 
-//================================================================
-// Function : create
-/*! Purpose  : Create data model*/
-//================================================================
+/*!
+  Creates data model
+*/
 bool SalomeApp_DataModel::create( CAM_Study* theStudy )
 {
   update(NULL, (LightApp_Study*)theStudy);
   return true;
 }
 
-//================================================================
-// Function : update
-/*! Purpose  : Update application.*/
-//================================================================
+/*!
+  Updates application.
+*/
 void SalomeApp_DataModel::update( LightApp_DataObject*, LightApp_Study* study )
 {
   SalomeApp_Study* aSStudy = dynamic_cast<SalomeApp_Study*>(study);
@@ -241,8 +320,7 @@ void SalomeApp_DataModel::update( LightApp_DataObject*, LightApp_Study* study )
       studyRoot = dynamic_cast<LightApp_RootObject*>( aSStudy->root() );
       QString anId = getRootEntry( aSStudy );
       if ( !anId.isEmpty() ){ // if nothing is published in the study for this module -> do nothing
-       _PTR(Study) aStudy ( aSStudy->studyDS() );
-       sobj = aStudy->FindComponentID( std::string( anId.latin1() ) );
+        sobj = SalomeApp_Application::getStudy()->FindComponentID( std::string( anId.toUtf8() ) );
       }
     }
   }
@@ -251,9 +329,8 @@ void SalomeApp_DataModel::update( LightApp_DataObject*, LightApp_Study* study )
     if ( studyRoot ) {
       aSStudy = dynamic_cast<SalomeApp_Study*>( studyRoot->study() ); // <study> value should not change here theoretically, but just to make sure
       if ( aSStudy ) {
-        _PTR(Study) aStudy ( aSStudy->studyDS() );
         // modelRoot->object() cannot be reused here: it is about to be deleted by buildTree() soon
-        sobj = aStudy->FindComponentID( std::string( modelRoot->entry().latin1() ) );
+        sobj = SalomeApp_Application::getStudy()->FindComponentID( std::string( modelRoot->entry().toUtf8() ) );
       }
     }
   }
@@ -261,37 +338,46 @@ void SalomeApp_DataModel::update( LightApp_DataObject*, LightApp_Study* study )
     updateTree( sobj, aSStudy );
 }
 
-//================================================================
-// Function : synchronize
-/*! Purpose  : synchronizes kernel tree and suit data tree starting from component 'sobj' */
-//================================================================
+/*!
+  Synchronizes kernel tree and suit data tree starting from component 'sobj'
+*/
 SUIT_DataObject* SalomeApp_DataModel::synchronize( const _PTR( SComponent )& sobj, SalomeApp_Study* study )
 {
   if( !study || !study->root() || !sobj )
     return 0;
-
+    
   DataObjectList ch; study->root()->children( ch );
   DataObjectList::const_iterator anIt = ch.begin(), aLast = ch.end();
-  SalomeApp_DataObject* suitObj = 0;
+  SUIT_DataObject* suitObj = 0;
   for( ; anIt!=aLast; anIt++ )
   {
-    SalomeApp_DataObject* dobj = dynamic_cast<SalomeApp_DataObject*>( *anIt );
-    if( dobj && dobj->name()==sobj->GetName().c_str() )
+    LightApp_DataObject* dobj = dynamic_cast<LightApp_DataObject*>( *anIt );
+    if( dobj && dobj->name() == sobj->GetName().c_str() )
     {
       suitObj = dobj;
       break;
     }
   }
 
+#ifdef WITH_SALOMEDS_OBSERVER
+  SalomeApp_RootObject* root=dynamic_cast<SalomeApp_RootObject*>(study->root());
+  if(!(root->toSynchronize()))
+    return suitObj;
+#endif
+
   SalomeApp_DataModelSync sync( study->studyDS(), study->root() );
 
-  return ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, suitObj, sync );
+  if( !suitObj || dynamic_cast<SalomeApp_DataObject*>( suitObj ) )
+    suitObj= ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, suitObj, sync );
+  else
+    suitObj= 0;
+
+  return suitObj;
 }
 
-//================================================================
-// Function : updateTree
-/*! Purpose  : updates tree.*/
-//================================================================
+/*!
+  Updates tree.
+*/
 void SalomeApp_DataModel::updateTree( const _PTR( SComponent )& comp, SalomeApp_Study* study )
 {
   SalomeApp_ModuleObject* aNewRoot = dynamic_cast<SalomeApp_ModuleObject*>( synchronize( comp, study ) );
@@ -302,20 +388,17 @@ void SalomeApp_DataModel::updateTree( const _PTR( SComponent )& comp, SalomeApp_
   }
 }
 
-//================================================================
-// Function : getModule
-/*! Purpose  : gets module*/
-//================================================================
-
+/*!
+  \return module
+*/
 SalomeApp_Module* SalomeApp_DataModel::getModule() const
 {
   return dynamic_cast<SalomeApp_Module*>( module() );
 }
 
-//================================================================
-// Function : getStudy
-/*! Purpose  : gets study */
-//================================================================
+/*!
+  \return study
+*/
 SalomeApp_Study* SalomeApp_DataModel::getStudy() const
 {
   if(!root()) return 0;
@@ -328,10 +411,9 @@ SalomeApp_Study* SalomeApp_DataModel::getStudy() const
   return aStudy;
 }
 
-//================================================================
-// Function : getRootEntry
-/*! Purpose  : returns study entry corresponding to this data model*/
-//================================================================
+/*!
+  \return study entry corresponding to this data model
+*/
 QString SalomeApp_DataModel::getRootEntry( SalomeApp_Study* study ) const
 {
   QString anEntry;
@@ -341,7 +423,7 @@ QString SalomeApp_DataModel::getRootEntry( SalomeApp_Study* study ) const
       anEntry = anObj->entry();
   }
   else if ( study && study->studyDS() ) { // this works even if <myRoot> is null
-    _PTR(SComponent) aSComp( study->studyDS()->FindComponent( module()->name() ) );
+    _PTR(SComponent) aSComp( study->studyDS()->FindComponent( module()->name().toStdString() ) );
     if ( aSComp )
       anEntry = aSComp->GetID().c_str();
   }