m->setAutoUpdate( on );
}
+/*!
+ \brief Get 'updateModified' flag value.
+ \return 'updateModified' flag value
+*/
+bool SUIT_DataBrowser::updateModified() const
+{
+ SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
+ return m ? m->updateModified() : false;
+}
+
+/*!
+ \brief Set 'updateModified' flag value.
+ \param on 'updateModified' flag value
+*/
+void SUIT_DataBrowser::setUpdateModified( const bool on )
+{
+ SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
+ if ( m )
+ m->setUpdateModified( on );
+}
+
/*!
\brief Update object browser starting from the object \obj;
open all branches automatically if \a autoOpen is \c true.
bool autoUpdate() const;
void setAutoUpdate( const bool );
+ bool updateModified() const;
+ void setUpdateModified( const bool );
+
void updateTree( SUIT_DataObject* = 0, const bool = true );
int updateKey() const;
signal()->emitInserted( obj, this );
}
+/*!
+ \brief Insert new child object into the list of the children (faster version of insertChild without signal).
+ \param obj child object being added
+ \param position child position
+*/
+void SUIT_DataObject::insertChildAtPos( SUIT_DataObject* obj, int position )
+{
+ if ( !obj )return;
+ int pos = position < 0 ? myChildren.count() : position;
+ myChildren.insert( qMin( pos, (int)myChildren.count() ), obj );
+ obj->assignParent( this );
+}
+
/*!
\brief Remove the specified child object reference.
\param obj child object being removed
parent()->appendChild( this );
}
+void SUIT_DataObject::assignParent( SUIT_DataObject* p )
+{
+ if ( p == myParent )
+ return;
+
+ myParent = p;
+}
+
/*!
\brief Get data object name.
virtual SUIT_DataObject* parent() const;
virtual void setParent( SUIT_DataObject* );
+ virtual void assignParent( SUIT_DataObject* );
+ void insertChildAtPos( SUIT_DataObject* obj, int position );
+ bool modified(){return _modified;};
+ void setModified(bool modified){_modified = modified;};
virtual QString name() const;
virtual QString text( const int = NameId ) const;
bool myCheck;
bool myAutoDel;
DataObjectList myChildren;
+ bool _modified;
static Signal* mySignal;
SUIT_DataObject* dataObject() const;
TreeItem* parent() const;
int position() const;
+ void setPosition(int position) {_position=position;};
int childCount() const;
TreeItem* child( const int i );
QList<TreeItem*> children() const;
TreeItem* myParent;
QList<TreeItem*> myChildren;
SUIT_DataObject* myObj;
+ int _position;
};
/*!
SUIT_TreeModel::TreeItem* parent,
SUIT_TreeModel::TreeItem* after )
: myParent( parent ),
- myObj( obj )
+ myObj( obj ),
+ _position(-1)
{
// Add <this> to the parent's children list
if ( myParent )
if ( !child )
return;
- int index = after ? myChildren.indexOf( after ) + 1 : 0;
+ int index = after ? after->position() + 1 : 0;
myChildren.insert( index, child );
}
*/
int SUIT_TreeModel::TreeItem::position() const
{
- return myParent ? myParent->myChildren.indexOf( (TreeItem*)this ) : -1;
+ return _position;
}
/*!
myRoot( 0 ),
myRootItem( 0 ),
myAutoDeleteTree( false ),
- myAutoUpdate( true )
+ myAutoUpdate( true ),
+ myUpdateModified( false )
{
initialize();
}
myRoot( root ),
myRootItem( 0 ),
myAutoDeleteTree( false ),
- myAutoUpdate( true )
+ myAutoUpdate( true ),
+ myUpdateModified( false )
{
initialize();
}
}
}
+/*!
+ \brief Get 'updateModified' flag value.
+ \return 'updateModified' flag value
+*/
+bool SUIT_TreeModel::updateModified() const
+{
+ return myUpdateModified;
+}
+/*!
+ \brief Set 'updateModified' flag value.
+ \param on 'updateModified' flag value
+*/
+void SUIT_TreeModel::setUpdateModified(const bool on)
+{
+ myUpdateModified=on;
+}
/*!
\brief Check if the specified column supports custom sorting.
updateTree( object( index ) );
}
+
+void SUIT_TreeModel::updateTreeModel(SUIT_DataObject* obj,TreeItem* item)
+{
+ int kobj=0;
+ int kitem=0;
+ int nobjchild=obj->childCount();
+ SUIT_DataObject* sobj=obj->childObject(kobj);
+ TreeItem* sitem = item->child(kitem);
+
+ while(kobj < nobjchild)
+ {
+ if(sitem==0)
+ {
+ //end of item list
+ if(kitem==0)
+ sitem=createItemAtPos(sobj,item,0);
+ else
+ sitem=createItemAtPos(sobj,item,kitem);
+ updateTreeModel(sobj,sitem);
+ kobj++;
+ kitem++;
+ sobj=obj->childObject(kobj);
+ sitem = item->child(kitem);
+ }
+ else if(sitem->dataObject() != sobj)
+ {
+ if(treeItem(sobj))
+ {
+ // item : to remove
+ removeItem(sitem);
+ sitem = item->child(kitem);
+ }
+ else
+ {
+ // obj : new object
+ createItemAtPos(sobj,item,kitem);
+ kobj++;
+ kitem++;
+ sobj=obj->childObject(kobj);
+ sitem = item->child(kitem);
+ }
+ }
+ else
+ {
+ //obj and item are synchronised : go to next ones
+ updateTreeModel(sobj,sitem);
+ if(sobj->modified()) updateItem(sitem);
+ if( sobj ) sobj->update();
+ kobj++;
+ kitem++;
+ sobj=obj->childObject(kobj);
+ sitem = item->child(kitem);
+ }
+ }
+ //remove remaining items
+ for(int i = item->childCount(); i > kitem;i--)
+ {
+ sitem = item->child(i-1);
+ removeItem(sitem);
+ }
+}
+
/*!
\brief Update tree model.
else if ( obj->root() != root() )
return;
- synchronize<ObjPtr,ItemPtr,SUIT_TreeModel::TreeSync>( obj,
- treeItem( obj ),
- SUIT_TreeModel::TreeSync( this ) );
+ if(updateModified())
+ {
+ updateTreeModel(obj,treeItem( obj ));
+ }
+ else
+ {
+ synchronize<ObjPtr,ItemPtr,SUIT_TreeModel::TreeSync>( obj,
+ treeItem( obj ),
+ SUIT_TreeModel::TreeSync( this ) );
+ }
emit modelUpdated();
}
myItems[ obj ] = new TreeItem( obj, parent, after );
+ for(int pos=row;pos < parent->childCount();pos++)
+ parent->child(pos)->setPosition(pos);
+
endInsertRows();
+ obj->setModified(false);
+
return myItems[ obj ];
}
+/*!
+ \brief Create an item corresponding to the data object.
+ \param obj source data object
+ \param parent parent tree item
+ \param pos tree item position into which new item should be inserted
+ \return created tree item or 0 if item could not be created
+*/
+SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItemAtPos( SUIT_DataObject* obj,
+ SUIT_TreeModel::TreeItem* parent,
+ int pos )
+{
+ if ( !obj )
+ return 0;
+
+ SUIT_DataObject* parentObj = object( parent );
+ QModelIndex parentIdx = index( parentObj );
+
+ int row = pos ;
+ SUIT_TreeModel::TreeItem* after = pos>0 ? parent->child(pos-1) : 0 ;
+
+ beginInsertRows( parentIdx, row, row );
+
+ SUIT_TreeModel::TreeItem* item = new TreeItem( obj, parent, after );
+ myItems[ obj ] = item;
+
+ for(int pos=row;pos < parent->childCount();pos++)
+ parent->child(pos)->setPosition(pos);
+
+ endInsertRows();
+
+ obj->setModified(false);
+
+ return item;
+}
+
/*!
\brief Update tree item.
\param item tree item to be updated
QModelIndex firstIdx = index( obj, 0 );
QModelIndex lastIdx = index( obj, columnCount() - 1 );
emit dataChanged( firstIdx, lastIdx );
+ obj->setModified(false);
}
/*!
// Warning! obj can be deleted at this point!
- SUIT_DataObject* parentObj = object( item->parent() );
+ TreeItem* parent=item->parent();
+ SUIT_DataObject* parentObj = object( parent );
QModelIndex parentIdx = index( parentObj, 0 );
int row = item->position();
if ( obj == root() )
setRoot( 0 );
- else if ( item->parent() )
- item->parent()->removeChild( item );
+ else if ( parent )
+ {
+ parent->removeChild( item );
+ for(int pos=row;pos < parent->childCount();pos++)
+ parent->child(pos)->setPosition(pos);
+ }
delete item;
return treeModel() ? treeModel()->autoUpdate() : false;
}
+/*!
+ \brief Get 'updateModified' flag value.
+ \return 'updateModified' flag value
+*/
+bool SUIT_ProxyModel::updateModified() const
+{
+ return treeModel() ? treeModel()->updateModified() : false;
+}
+/*!
+ \brief Set 'updateModified' flag value.
+
+ If this flag is set to \c true (default=false), the model is updated by updateTreeModel that
+ uses the isModified flag to update only modified objects
+
+ \param on 'updateModified' flag value
+*/
+void SUIT_ProxyModel::setUpdateModified( const bool on )
+{
+ if ( treeModel() )
+ treeModel()->setUpdateModified( on );
+}
+
/*!
\brief Set 'auto-update tree' flag value.
virtual void setAutoDeleteTree( const bool ) = 0;
virtual bool autoUpdate() const = 0;
virtual void setAutoUpdate( const bool ) = 0;
+ virtual bool updateModified() const = 0;
+ virtual void setUpdateModified( const bool ) = 0;
virtual QAbstractItemDelegate* delegate() const = 0;
virtual bool customSorting( const int ) const = 0;
virtual bool lessThan( const QModelIndex& left, const QModelIndex& right ) const = 0;
bool autoUpdate() const;
void setAutoUpdate( const bool );
+ bool updateModified() const;
+ void setUpdateModified( const bool );
+
virtual bool customSorting( const int ) const;
virtual bool lessThan( const QModelIndex& left, const QModelIndex& right ) const;
QAbstractItemDelegate* delegate() const;
+ virtual void updateTreeModel(SUIT_DataObject*,TreeItem*);
+
public slots:
virtual void updateTree( const QModelIndex& );
virtual void updateTree( SUIT_DataObject* = 0 );
SUIT_DataObject* object( const TreeItem* ) const;
TreeItem* createItem( SUIT_DataObject*, TreeItem* = 0, TreeItem* = 0 );
+ TreeItem* createItemAtPos( SUIT_DataObject*, TreeItem* = 0, int pos=0 );
void updateItem( TreeItem* );
void removeItem( TreeItem* );
ItemMap myItems;
bool myAutoDeleteTree;
bool myAutoUpdate;
+ bool myUpdateModified;
QVector<ColumnInfo> myColumns;
friend class SUIT_TreeModel::TreeSync;
bool autoUpdate() const;
void setAutoUpdate( const bool );
-
+
+ bool updateModified() const;
+ void setUpdateModified( const bool );
+
bool isSortingEnabled() const;
bool customSorting( const int ) const;
#include <vector>
+//To activate update of Object Browser with SALOMEDS::Observer uncomment following line
+#define WITH_SALOMEDS_OBSERVER
+
/*!Internal class that updates object browser item properties */
// temporary commented
/*class SalomeApp_Updater : public OB_Updater
// temporary commented
//ob->setUpdater( new SalomeApp_Updater() );
+#ifdef WITH_SALOMEDS_OBSERVER
+ //do not activate the automatic update of Qt tree through signal/slot
+ ob->setAutoUpdate(false);
+ //activate update of modified objects only
+ ob->setUpdateModified(true);
+#endif
+
connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
QString
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SALOME_Exception)
+//To activate update of Object Browser with SALOMEDS::Observer uncomment following line
+#define WITH_SALOMEDS_OBSERVER
+
typedef _PTR(SObject) kerPtr;
typedef SUIT_DataObject* suitPtr;
}
}
+#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() );
if( !suitObj || dynamic_cast<SalomeApp_DataObject*>( suitObj ) )
- return ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, suitObj, sync );
+ suitObj= ::synchronize<kerPtr,suitPtr,SalomeApp_DataModelSync>( sobj, suitObj, sync );
else
- return 0;
+ suitObj= 0;
+
+#ifdef WITH_SALOMEDS_OBSERVER
+ root->setToSynchronize(false);
+#endif
+
+ return suitObj;
}
/*!
return val;
}
+void SalomeApp_DataObject::insertChildAtTag(SalomeApp_DataObject* obj,int tag)
+{
+ int pos=0;
+ int npos=std::min(tag-1,childCount());
+ for (int i=npos;i>0;i--)
+ {
+ if((dynamic_cast<SalomeApp_DataObject*>(childObject(i-1)))->object()->Tag() < tag)
+ {
+ pos=i-1;
+ break;
+ }
+ }
+ insertChildAtPos(obj,pos+1);
+}
+
+void SalomeApp_DataObject::updateItem()
+{
+ if(modified())return;
+ setModified(true);
+}
+
/*!
\class SalomeApp_ModuleObject
\brief This class is used for optimized access to the SALOMEDS-based
: CAM_DataObject( 0 ),
LightApp_DataObject( 0 ),
SalomeApp_DataObject( 0 ),
- LightApp_RootObject( study )
+ LightApp_RootObject( study ),
+ _toSynchronize(true)
{
}
virtual bool customSorting( const int = NameId ) const;
virtual bool compare( const QVariant&, const QVariant&, const int = NameId ) const;
+ virtual void insertChildAtTag( SalomeApp_DataObject*, int );
+ virtual void updateItem();
+
private:
QString ior( const _PTR(SObject)& ) const;
QString entry( const _PTR(SObject)& ) const;
QPixmap icon( const int = NameId ) const;
QColor color( const ColorRole, const int = NameId ) const;
QString toolTip( const int = NameId ) const;
+ void setToSynchronize(bool value){_toSynchronize=value;};
+ bool toSynchronize() const {return _toSynchronize;};
+protected:
+ bool _toSynchronize;
};
class SALOMEAPP_EXPORT SalomeApp_SavePointObject : public virtual LightApp_DataObject
#include "SalomeApp_Application.h"
#include "SalomeApp_Engine_i.hxx"
#include "SalomeApp_VisualState.h"
+#include "SUIT_TreeModel.h"
+#include "SUIT_DataBrowser.h"
// temporary commented
//#include <OB_Browser.h>
using namespace std;
+//To activate update of Object Browser with SALOMEDS::Observer uncomment following line
+#define WITH_SALOMEDS_OBSERVER
+
+class Observer_i : public virtual POA_SALOMEDS::Observer
+{
+ public:
+
+ Observer_i(_PTR(Study) aStudyDS, SalomeApp_Study* aStudy)
+ {
+ myStudyDS=aStudyDS;
+ myStudy=aStudy;
+ }
+
+ virtual void notifyObserverID(const char* theID, ::CORBA::Long event)
+ {
+ SalomeApp_DataObject* suit_obj;
+
+ if (event == 1) // add sobject
+ {
+ if (entry2SuitObject.count(theID)>0)
+ {
+ std::cerr << "entry " << theID << " is already added. Problem ??" << std::endl;
+ return;
+ }
+ _PTR(SObject) obj = myStudyDS->FindObjectID( theID );
+ std::string entry_str = theID;
+ int last2Pnt_pos = entry_str.rfind(":");
+ std::string parent_id=entry_str.substr(0,last2Pnt_pos);
+ std::string pos_in_parent=entry_str.substr(last2Pnt_pos+1);
+
+ if(parent_id.length() == 3 )
+ {
+ //It's probably a SComponent
+ _PTR(SComponent) aSComp=obj->GetFatherComponent();
+ if( aSComp->GetID() == entry_str )
+ suit_obj=new SalomeApp_ModuleObject(aSComp,0);
+ else
+ suit_obj=new SalomeApp_DataObject(obj,0);
+ }
+ else
+ suit_obj=new SalomeApp_DataObject(obj,0);
+
+ if (entry2SuitObject.count(parent_id)>0)
+ {
+ SalomeApp_DataObject* father=entry2SuitObject[parent_id];
+ int tag=atoi(pos_in_parent.c_str());
+ father->insertChildAtTag(suit_obj,tag);
+ }
+ else
+ {
+ if(parent_id.length() == 3 )
+ {
+ // This should be for a module
+ SUIT_DataObject* father=myStudy->root();
+ father->appendChild(suit_obj);
+ }
+ else
+ {
+ //Try to find the SalomeApp_DataObject object parent
+ std::string root_id=parent_id.substr(0,4);
+ std::string obj_id=parent_id.substr(4);
+
+ std::string anID;
+ string::size_type debut =0;
+ string::size_type fin;
+ SalomeApp_DataObject* anObj=dynamic_cast<SalomeApp_DataObject*>(myStudy->root());
+ while(1)
+ {
+ fin=obj_id.find_first_of(':',debut);
+ if(fin == std::string::npos)
+ {
+ //last id
+ anObj = dynamic_cast<SalomeApp_DataObject*>(anObj->childObject(atoi(obj_id.substr(debut).c_str())-1));
+ entry2SuitObject[parent_id]=anObj;
+ break;
+ }
+ anID=root_id+obj_id.substr(0,fin);
+ if (entry2SuitObject.count(anID) == 0)
+ {
+ //the ID is not known in entry2SuitObject
+ anObj = dynamic_cast<SalomeApp_DataObject*>(anObj->childObject(atoi(obj_id.substr(debut,fin-debut).c_str())-1));
+ entry2SuitObject[anID]=anObj;
+ }
+ else
+ anObj=entry2SuitObject[anID];
+ debut=fin+1;
+ }
+ int tag=atoi(pos_in_parent.c_str());
+ anObj->insertChildAtTag(suit_obj,tag);
+ }
+ }
+ entry2SuitObject[theID]=suit_obj;
+ }
+ else if (event == 2) // remove sobject
+ {
+ if (entry2SuitObject.count(theID)>0)
+ {
+ suit_obj= entry2SuitObject[theID];
+ SUIT_DataObject* father=suit_obj->parent();
+ if(father)
+ father->removeChild(suit_obj);
+ entry2SuitObject.erase(theID);
+ }
+ else
+ {
+ MESSAGE("Want to remove an unknown object" << theID);
+ }
+ }
+ else if (event == 0) //modify sobject
+ {
+ if (entry2SuitObject.count(theID)>0)
+ {
+ suit_obj= entry2SuitObject[theID];
+ suit_obj->updateItem();
+ }
+ else
+ {
+ MESSAGE("Want to modify an unknown object" << theID);
+ }
+ }
+ else
+ {
+ MESSAGE("Unknown event: " << event);
+ }
+ }
+
+ private:
+ _PTR(Study) myStudyDS;
+ SalomeApp_Study* myStudy;
+ map<string,SalomeApp_DataObject*> entry2SuitObject;
+};
+
+
/*!
Constructor.
*/
*/
bool SalomeApp_Study::createDocument( const QString& theStr )
{
- MESSAGE( "openDocument" );
+ MESSAGE( "createDocument" );
// initialize myStudyDS, read HDF file
QString aName = newStudyName();
setStudyName( aName );
// create myRoot
- setRoot( new SalomeApp_RootObject( this ) );
+ SalomeApp_RootObject* aRoot=new SalomeApp_RootObject( this );
+ aRoot->setToSynchronize(false);
+ setRoot( aRoot );
bool aRet = CAM_Study::createDocument( theStr );
emit created( this );
+#ifdef WITH_SALOMEDS_OBSERVER
+ Observer_i* myObserver_i = new Observer_i(myStudyDS,this);
+ //attach an observer to the study with notification of modifications
+ myStudyDS->attach(myObserver_i->_this(),true);
+#endif
+
return aRet;
}
// but tree that corresponds to not-loaded data models will be updated any way.
((SalomeApp_Application*)application())->updateObjectBrowser( false );
+#ifdef WITH_SALOMEDS_OBSERVER
+ Observer_i* myObserver_i = new Observer_i(myStudyDS,this);
+ //attach an observer to the study with notification of modifications
+ myStudyDS->attach(myObserver_i->_this(),true);
+#endif
+
bool res = CAM_Study::openDocument( theFileName );
emit opened( this );
// but tree that corresponds to not-loaded data models will be updated any way.
((SalomeApp_Application*)application())->updateObjectBrowser( false );
+#ifdef WITH_SALOMEDS_OBSERVER
+ Observer_i* myObserver_i = new Observer_i(myStudyDS,this);
+ //attach an observer to the study with notification of modifications
+ myStudyDS->attach(myObserver_i->_this(),true);
+#endif
+
bool res = CAM_Study::openDocument( theStudyName );
emit opened( this );
private:
_PTR(Study) myStudyDS;
+
+private:
+ SALOMEDS::Observer_var myObserver;
};
#ifdef WIN32