1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: SUIT_TreeModel.cxx
21 // Author: Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
23 #include "SUIT_Session.h"
24 #include "SUIT_TreeModel.h"
25 #include "SUIT_TreeSync.h"
26 #include "SUIT_DataObject.h"
27 #include "SUIT_ResourceMgr.h"
29 #include <QApplication>
33 SUIT_AbstractModel::SUIT_AbstractModel() : mySearcher( 0 )
37 SUIT_AbstractModel::operator const QAbstractItemModel*() const
39 return dynamic_cast<const QAbstractItemModel*>( this );
42 SUIT_AbstractModel::operator QAbstractItemModel*()
44 return dynamic_cast<QAbstractItemModel*>( this );
47 SUIT_AbstractModel::operator const QObject*() const
49 return dynamic_cast<const QObject*>( this );
52 SUIT_DataSearcher* SUIT_AbstractModel::searcher() const
57 void SUIT_AbstractModel::setSearcher( SUIT_DataSearcher* s )
64 \class SUIT_TreeModel::TreeItem
65 \brief Internal class used for tree view synchronizaton with data object tree.
69 class SUIT_TreeModel::TreeItem
72 TreeItem( SUIT_DataObject* obj, TreeItem* parent = 0, TreeItem* after = 0 );
75 void insertChild( TreeItem* child, TreeItem* after = 0 );
76 void removeChild( TreeItem* child );
77 SUIT_DataObject* dataObject() const;
78 TreeItem* parent() const;
80 void setPosition(int position) {_position=position;};
81 int childCount() const;
82 TreeItem* child( const int i );
83 QList<TreeItem*> children() const;
84 TreeItem* nextSibling() const;
85 TreeItem* prevSibling() const;
89 QList<TreeItem*> myChildren;
90 SUIT_DataObject* myObj;
97 \param obj data object
98 \param parent parent item
99 \param after tree item after each this one should be inserted
101 SUIT_TreeModel::TreeItem::TreeItem( SUIT_DataObject* obj,
102 SUIT_TreeModel::TreeItem* parent,
103 SUIT_TreeModel::TreeItem* after )
104 : myParent( parent ),
108 // Add <this> to the parent's children list
110 myParent->insertChild( this, after );
114 \brief Destructor. Deletes all child items recursively.
117 SUIT_TreeModel::TreeItem::~TreeItem()
119 // Ensure that all children are deleted;
120 // each child removes itself from the children list
121 while( myChildren.count() )
122 delete myChildren.at( 0 );
124 // Remove this item from the parent's children list
126 myParent->removeChild( this );
130 \brief Insert child item.
132 \param child child item being inserted
133 \param after tree item after each \a child should be inserted
135 void SUIT_TreeModel::TreeItem::insertChild( SUIT_TreeModel::TreeItem* child,
136 SUIT_TreeModel::TreeItem* after )
141 int index = after ? after->position() + 1 : 0;
142 myChildren.insert( index, child );
146 \brief Remove child item.
148 \param child child item being removed
150 void SUIT_TreeModel::TreeItem::removeChild( SUIT_TreeModel::TreeItem* child )
154 myChildren.removeAll( child );
158 \brief Get data object.
160 \return data object this item is associated to
162 SUIT_DataObject* SUIT_TreeModel::TreeItem::dataObject() const
168 \brief Get parent item.
172 SUIT_TreeModel::TreeItem* SUIT_TreeModel::TreeItem::parent() const
178 \brief Get position of this item in its parent's children list.
180 \return item position
182 int SUIT_TreeModel::TreeItem::position() const
188 \brief Get number of child items.
190 \return number of children
192 int SUIT_TreeModel::TreeItem::childCount() const
194 return myChildren.count();
198 \brief Get child item by specified index.
200 \param i child item index
201 \return child item or 0 if \a i is out of range
203 SUIT_TreeModel::TreeItem* SUIT_TreeModel::TreeItem::child( const int i )
205 return i >= 0 && i < myChildren.count() ? myChildren.at( i ) : 0;
209 \brief Get all child items.
211 \return list of child items
213 QList<SUIT_TreeModel::TreeItem*> SUIT_TreeModel::TreeItem::children() const
219 \brief Get next sibling item.
221 \return next sibling item or 0 if there are no any
223 SUIT_TreeModel::TreeItem* SUIT_TreeModel::TreeItem::nextSibling() const
225 return parent() ? parent()->child( position()+1 ) : 0;
229 \brief Get previous sibling item.
231 \return previous sibling item or 0 if there are no any
233 SUIT_TreeModel::TreeItem* SUIT_TreeModel::TreeItem::prevSibling() const
235 return parent() ? parent()->child( position()-1 ) : 0;
239 \class SUIT_TreeModel::TreeSync
240 \brief Functor class for synchronizing data tree and tree model
241 when the data tree is changed outside the model.
245 class SUIT_TreeModel::TreeSync
248 TreeSync( SUIT_TreeModel* );
249 bool isEqual( const ObjPtr&, const ItemPtr& ) const;
250 ObjPtr nullSrc() const;
251 ItemPtr nullTrg() const;
252 ItemPtr createItem( const ObjPtr&, const ItemPtr&, const ItemPtr& ) const;
253 void updateItem( const ObjPtr&, const ItemPtr& ) const;
254 void deleteItemWithChildren( const ItemPtr& ) const;
255 QList<ObjPtr> children( const ObjPtr& ) const;
256 QList<ItemPtr> children( const ItemPtr& ) const;
257 ItemPtr parent( const ItemPtr& ) const;
259 bool needUpdate( const ItemPtr& ) const;
260 SUIT_TreeModel* myModel;
266 \param model tree model
268 SUIT_TreeModel::TreeSync::TreeSync( SUIT_TreeModel* model )
274 \brief Check if item corresponds to the specified data object.
276 \param obj data object
277 \param item tree item
278 \return \c true if item corresponds to the data object
280 bool SUIT_TreeModel::TreeSync::isEqual( const ObjPtr& obj, const ItemPtr& item ) const
282 bool isRoot = obj == myModel->root() && item == myModel->rootItem(),
283 isEq = obj && item && item->dataObject() == obj;
284 return isRoot || ( !obj && !item ) || isEq;
288 \brief Get null data object.
290 \return null data object
292 SUIT_TreeModel::ObjPtr SUIT_TreeModel::TreeSync::nullSrc() const
298 \brief Get null tree item.
300 \return null tree item
302 SUIT_TreeModel::ItemPtr SUIT_TreeModel::TreeSync::nullTrg() const
308 \brief Create an item corresponding to the specified data object.
310 \param obj data object
311 \param parent parent tree item
312 \param after tree item after each new one should be inserted
315 SUIT_TreeModel::ItemPtr SUIT_TreeModel::TreeSync::createItem( const ObjPtr& obj,
316 const ItemPtr& parent,
317 const ItemPtr& after ) const
319 ItemPtr item = myModel ? myModel->createItem( obj, parent, after ) : 0;
321 // Additional actions that can't be performed by the model, e.g. expanded state
328 \brief Update tree item.
330 \param obj reference data object
331 \param item tree item to be updated
333 void SUIT_TreeModel::TreeSync::updateItem( const ObjPtr& obj, const ItemPtr& item ) const
337 if ( item && needUpdate( item ) )
338 myModel->updateItem( item, false );
342 \brief Delete item with all children recursively.
344 \param item tree item
346 void SUIT_TreeModel::TreeSync::deleteItemWithChildren( const ItemPtr& item ) const
348 // NOTE: item is deleted inside removeItem()!
349 myModel->removeItem( item );
353 \brief Get all the children of the specified data object.
355 \param obj data object
356 \return list of the children
358 QList<SUIT_TreeModel::ObjPtr> SUIT_TreeModel::TreeSync::children( const ObjPtr& obj ) const
362 ch = obj->children();
367 \brief Get all the children of the specified tree item.
369 \param item tree item
370 \return list of the children
372 QList<SUIT_TreeModel::ItemPtr> SUIT_TreeModel::TreeSync::children( const ItemPtr& item ) const
376 ch = item->children();
381 \brief Get item which is the parent for the specified item.
383 \param item tree item
386 SUIT_TreeModel::ItemPtr SUIT_TreeModel::TreeSync::parent( const ItemPtr& item ) const
388 return item ? item->parent() : 0;
392 \brief Check if the tree item needs updating.
394 \param item tree item to be checked
395 \return \c true if item needs updating
397 \todo finalize this method
399 bool SUIT_TreeModel::TreeSync::needUpdate( const ItemPtr& item ) const
403 SUIT_DataObject* obj = item->dataObject();
405 // TODO: find simplified way to check if an item is not up-to-date:
406 // - use check-sum of various item data
407 // - use "LastModified" time stamp in data objects and tree items - hardly possible, for sometimes data objects do not know that data changes...
409 update = true; // TEMPORARY!!!
411 /* update = ( item->text( 0 ) != obj->name() ) || myBrowser->needToUpdateTexts( item );
414 // 2. check pixmap (compare serialNumber()-s)
415 QPixmap objPix = obj->icon();
416 const QPixmap* itemPix = item->pixmap( 0 );
417 update = ( objPix.isNull() && ( itemPix && !itemPix->isNull() ) ) ||
418 ( !objPix.isNull() && ( !itemPix || itemPix->isNull() ) );
419 if ( !update && !objPix.isNull() && itemPix && !itemPix->isNull() ) {
420 int aIconW = objPix.width();
423 double aScale = 20.0 / aIconW;
424 aM.scale( aScale, aScale );
425 objPix = objPix.xForm( aM );
427 update = ( objPix.serialNumber() != itemPix->serialNumber() );
436 \class SUIT_TreeModel
437 \brief Implementation of the model/view API based on the tree of SUIT_DataObject class
440 The SUIT_TreeModel class does not support insertion/removal of rows. It is synchronized
441 automatically with the tree of data objects used by SUIT-based applications to
442 expose their data in a hierarchical form to the user.
447 \param parent parent object
449 SUIT_TreeModel::SUIT_TreeModel( QObject* parent )
450 : QAbstractItemModel( parent ),
453 myAutoDeleteTree( false ),
454 myAutoUpdate( true ),
455 myUpdateModified( false )
462 \param root root data object
463 \param parent parent object
465 SUIT_TreeModel::SUIT_TreeModel( SUIT_DataObject* root, QObject* parent )
466 : QAbstractItemModel( parent ),
469 myAutoDeleteTree( false ),
470 myAutoUpdate( true ),
471 myUpdateModified( false )
479 SUIT_TreeModel::~SUIT_TreeModel()
481 if ( autoDeleteTree() ) {
482 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
483 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
484 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
485 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
486 SUIT_DataObject::disconnect( SIGNAL( modifed( SUIT_DataObject* ) ),
487 this, SLOT( onModified( SUIT_DataObject* ) ) );
495 \brief Register new column in the model
496 \param group_id - unique data object group identificator
497 \param name - translated column name
498 \param custom_id - custom column id that should be passed into method SUIT_DataObject::data()
500 void SUIT_TreeModel::registerColumn( const int group_id, const QString& name, const int custom_id )
503 for ( int i=0, n=myColumns.size(); i<n && !found; i++ ) {
504 if ( name == myColumns[i].myName ) {
505 myColumns[i].myIds.insert( group_id, custom_id );
512 inf.myIds.insert( group_id, custom_id );
513 inf.myAppropriate = Qtx::Shown;
514 inf.myHeaderFlags = Qtx::ShowAll;
515 int n = myColumns.size();
516 myColumns.resize( n+1 );
523 \brief Remove column from the model
525 Please take into account that column is removed only for given group_id, it means
526 that information of data objects with such group_id won't be shown.
527 If there is not any registered group_id for this column after removing, the column will be hidden
528 otherwise it continue to be shown
530 \param group_id - unique data object identificator allowing the classification of objects
531 \param name - translated column name
533 void SUIT_TreeModel::unregisterColumn( const int group_id, const QString& name )
535 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
536 if ( myColumns[i].myName == name ) {
537 myColumns[i].myIds.remove( group_id );
538 if ( myColumns[i].myIds.isEmpty() ) {
539 myColumns.remove( i );
548 \brief Change column icon.
550 \param name - column name
551 \param icon - new icon of the specified column
553 void SUIT_TreeModel::setColumnIcon( const QString& name, const QPixmap& icon )
555 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
556 if ( myColumns[i].myName == name ) {
557 myColumns[i].myIcon = icon;
564 \brief Get column icon.
566 \param name - column name
567 \return icon of the specified column
569 QPixmap SUIT_TreeModel::columnIcon( const QString& name ) const
572 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
573 if ( myColumns[i].myName == name ) {
574 res = myColumns[i].myIcon;
582 \brief Change appropriate status
584 Appropriate status determines if the column should appear in the tree view header popup menu
585 (to show/hide the column).
587 If appropriate status is not specified yet, the \c Shown value is taken,
588 it means that column should be always visible.
590 \param name - column name
591 \param appr - new appropriate status
593 void SUIT_TreeModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
595 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
596 if ( myColumns[i].myName == name && myColumns[i].myAppropriate != appr ) {
597 myColumns[i].myAppropriate = appr;
598 emit headerDataChanged( Qt::Horizontal, i, i );
605 \brief Check if the column should appear in the tree view header popup menu
606 (to show/hide the column).
608 Default implementation (if appropriate status is not specified yet)
609 returns \c Shown, it means that column should be always visible.
611 \param name - column name
612 \return appropriate status
614 Qtx::Appropriate SUIT_TreeModel::appropriate( const QString& name ) const
616 Qtx::Appropriate appr = Qtx::Shown;
617 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
618 if ( myColumns[i].myName == name ) {
619 appr = myColumns[i].myAppropriate;
628 \brief Set header flags.
630 These flags allow show in the header of the column text (name of the column),
631 icon or both text and icon.
633 \param name - column name
634 \param flags - header flags
637 void SUIT_TreeModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
639 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
640 if ( myColumns[i].myName == name && myColumns[i].myHeaderFlags != flags ) {
641 myColumns[i].myHeaderFlags = flags;
642 emit headerDataChanged( Qt::Horizontal, i, i );
649 \brief Get the header flags.
651 These flags allow show in the header of the column text (name of the column),
652 icon or both text and icon.
654 \param name - column name
657 Qtx::HeaderViewFlags SUIT_TreeModel::headerFlags( const QString& name ) const
659 Qtx::HeaderViewFlags flags;
660 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
661 if ( myColumns[i].myName == name ) {
662 flags = myColumns[i].myHeaderFlags;
670 \brief Set visibility state of the object.
672 \param id - column name
673 \param state - visible state
674 \param emitChanged - if set to false, blocks dataChanged() signal, this can be used to
675 prevent emitting dataChanged() several times for the same data object
677 void SUIT_TreeModel::setVisibilityState( const QString& id, Qtx::VisibilityState state, bool emitChanged )
679 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
680 if ( it != myVisibilityMap.end() && it.value() == state )
683 bool needSignal = false;
684 if ( state != Qtx::UnpresentableState ) {
685 myVisibilityMap.insert( id, state );
689 needSignal = myVisibilityMap.remove( id ) > 0;
691 if ( emitChanged && needSignal ) {
694 SUIT_DataObject* o = searcher()->findObject( id );
695 if ( o ) lst << index( o );
698 lst = match( index( 0, root()->customData( Qtx::IdType ).toInt() ), DisplayRole, id, 1, Qt::MatchExactly | Qt::MatchRecursive );
700 if ( !lst.isEmpty() ) {
701 QModelIndex idx = index( lst.first().row(), SUIT_DataObject::VisibilityId, lst.first().parent() );
702 emit dataChanged( idx, idx );
708 \brief Set visibility state for all objects.
710 \param state - visible state
712 void SUIT_TreeModel::setVisibilityStateForAll( Qtx::VisibilityState state )
714 if ( state != Qtx::UnpresentableState ) {
715 VisibilityMap::ConstIterator it = myVisibilityMap.begin();
716 while ( it != myVisibilityMap.end() ) {
717 if ( it.value() != state )
718 setVisibilityState( it.key(), state );
723 QList<QString> anIds = myVisibilityMap.keys();
724 myVisibilityMap.clear();
725 QList<QString>::ConstIterator it = anIds.begin();
726 while ( it != anIds.end() ) {
729 SUIT_DataObject* o = searcher()->findObject( *it );
730 if ( o ) lst << index( o );
733 lst = match( index( 0, root()->customData( Qtx::IdType ).toInt() ), DisplayRole, (*it), 1, Qt::MatchExactly | Qt::MatchRecursive );
735 if ( !lst.isEmpty() ) {
736 QModelIndex idx = index( lst.first().row(), SUIT_DataObject::VisibilityId ,lst.first().parent() );
737 emit dataChanged( idx, idx );
745 \brief Get visibility state of the object.
747 \param id - column name
748 \return visible state
750 Qtx::VisibilityState SUIT_TreeModel::visibilityState( const QString& id ) const
752 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
753 return it != myVisibilityMap.end() ? it.value() : Qtx::UnpresentableState;
757 \brief Get data tree root object.
758 \return data tree root
761 SUIT_DataObject* SUIT_TreeModel::root() const
767 \brief Set data tree root object.
768 \param r new data tree root
771 void SUIT_TreeModel::setRoot( SUIT_DataObject* r )
776 if ( autoDeleteTree() ) {
777 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
778 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
779 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
780 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
781 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
782 this, SLOT( onModified( SUIT_DataObject* ) ) );
786 QList<TreeItem*> items = myRootItem->children();
787 for ( QList<TreeItem*>::iterator anIt = items.begin(); anIt != items.end(); anIt++ )
800 \brief Get data for the specified model index and data role.
801 \param index model index
802 \param role data role
803 \return requested data
806 QVariant SUIT_TreeModel::data( const QModelIndex& index, int role ) const
808 if ( !index.isValid() )
811 SUIT_DataObject* obj = object( index );
818 int obj_group_id = obj->groupId();
819 const ColumnInfo& inf = myColumns[index.column()];
822 if( inf.myIds.contains( 0 ) )
824 if( inf.myIds.contains( obj_group_id ) )
825 id = inf.myIds[obj_group_id];
835 // data object text for the specified column
836 val = obj->text( id );
839 // data object text for the specified column (for editor)
840 val = obj->text( id );
842 case DecorationRole: {
844 if ( id == SUIT_DataObject::VisibilityId ) {
845 // for visibility column, icon is defined specifically (using data object id)
846 QString objId = objectId( index );
847 if ( myVisibilityMap.contains( objId ) ) {
848 // visibility status is defined -> return proper icon
849 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
850 val = ( myVisibilityMap.value( objId ) == Qtx::ShownState ) ?
851 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ) :
852 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_INVISIBLE" ) );
855 // visibility status is undefined -> no icon
860 // for other columns get icon from the object
861 val = obj->icon( id );
866 // data object tooltip for the specified column
867 val = obj->toolTip( id );
870 // data object status tip for the specified column
871 val = obj->statusTip( id );
874 // data object what's this info for the specified column
875 val = obj->whatsThis( id );
878 // data object font for the specified column
879 val = obj->font( id );
881 case TextAlignmentRole:
882 // data object text alignment for the specified column
883 val = obj->alignment( id );
886 // data background color for the specified column
887 c = obj->color( SUIT_DataObject::Background, id );
888 if( !c.isValid() ) // default value
889 c = QApplication::palette().color( QPalette::Base );
894 // data foreground (text) color for the specified column
895 c = obj->color( SUIT_DataObject::Foreground, id );
896 if( !c.isValid() ) // default value
897 c = QApplication::palette().color( QPalette::Foreground );
901 // editor background color for the specified column
902 c = obj->color( SUIT_DataObject::Base, id );
903 if( !c.isValid() ) // default value
904 c = QApplication::palette().color( QPalette::Base );
908 // editor foreground (text) color for the specified column
909 c = obj->color( SUIT_DataObject::Text, id );
910 if( !c.isValid() ) // default value
911 c = QApplication::palette().color( QPalette::Text );
915 // adta object highlighted background color for the specified column
916 c = obj->color( SUIT_DataObject::Highlight, id );
917 if( !c.isValid() ) // default value
918 c = QApplication::palette().color( QPalette::Highlight );
921 case HighlightedTextRole:
922 // data object highlighted foreground (text) color for the specified column
923 c = obj->color( SUIT_DataObject::HighlightedText, id );
924 if( !c.isValid() ) // default value
925 c = QApplication::palette().color( QPalette::HighlightedText );
929 // data object checked state for the specified column
930 // NOTE! three-state check is not supported currently
931 if( obj->isCheckable( id ) )
932 val = obj->isOn( id ) ? Qt::Checked : Qt::Unchecked;
936 // NOTE! not supported currently
940 } // ... switch ( role ) ...
941 } // ... if ( obj ) ...
946 \brief Set data for the specified model index and data role.
947 \param index model index
948 \param value new data value
949 \param role data role
950 \return \c true if data is set
953 bool SUIT_TreeModel::setData( const QModelIndex& index,
954 const QVariant& value, int role )
956 if ( index.isValid() && value.isValid() ) {
957 SUIT_DataObject* obj = object( index );
959 // NOTE! only 'check state' data is supported by default
963 if ( obj->isCheckable( index.column() ) ) {
964 obj->setOn( value.toBool(), index.column() );
965 emit( dataChanged( index, index ) );
970 QString val = value.toString();
971 if ( !val.isEmpty() && obj->setName(val) ) {
972 emit( dataChanged( index, index ) );
983 return QAbstractItemModel::setData( index, value, role );
987 \brief Get data flags for specified model index.
988 \param index model index
991 Qt::ItemFlags SUIT_TreeModel::flags( const QModelIndex& index ) const
995 if (!index.isValid())
996 //return Qt::ItemIsDropEnabled; // items can be dropped into the top level of the model
999 SUIT_DataObject* obj = object(index);
1002 // data object is enabled
1003 if (obj->isEnabled())
1004 f = f | Qt::ItemIsEnabled;
1006 // data object is selectable
1007 if (obj->isSelectable())
1008 f = f | Qt::ItemIsSelectable;
1010 // data object is checkable
1011 if (obj->isCheckable(index.column()))
1012 f = f | Qt::ItemIsUserCheckable;
1014 // data object can be renamed
1015 if (obj->renameAllowed(index.column()))
1016 f = f | Qt::ItemIsEditable;
1018 // data object can be dragged
1019 if (obj->isDraggable())
1020 f = f | Qt::ItemIsDragEnabled;
1022 // another data object(s) can be dropped on this one
1023 if (obj->isDropAccepted())
1024 f = f | Qt::ItemIsDropEnabled;
1030 Qt::DropActions SUIT_TreeModel::supportedDropActions() const
1032 return Qt::CopyAction | Qt::MoveAction;
1036 \brief Get header data (can be used in any data view).
1037 \param column column number
1038 \param orientation header orientation
1039 \param role data role
1042 QVariant SUIT_TreeModel::headerData( int column, Qt::Orientation orientation, int role ) const
1045 // NOTE! only horizontal header is supported
1046 if ( root() && orientation == Qt::Horizontal )
1052 if((myColumns[column].myHeaderFlags & Qtx::ShowText) ||
1053 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1054 d = myColumns[column].myName;
1058 case DecorationRole:
1060 if((myColumns[column].myHeaderFlags & Qtx::ShowIcon) ||
1061 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1062 d = myColumns[column].myIcon;
1066 case AppropriateRole:
1067 // appropriate flag (can column be hidden via context popup menu)
1068 d = myColumns[column].myAppropriate;
1078 \brief Create model index.
1080 \param column data column
1081 \param parent parent model index
1084 QModelIndex SUIT_TreeModel::index( int row, int column,
1085 const QModelIndex& parent ) const
1087 if( hasIndex( row, column, parent ) )
1089 TreeItem* parentItem = treeItem( parent );
1092 TreeItem* childItem = parentItem->child( row );
1094 return createIndex( row, column, childItem );
1097 return QModelIndex();
1101 \brief Get parent model index.
1102 \param index model index
1103 \return parent model index
1105 QModelIndex SUIT_TreeModel::parent( const QModelIndex& index ) const
1107 if ( !index.isValid() )
1108 return QModelIndex();
1110 TreeItem* childItem = treeItem( index );
1111 TreeItem* parentItem = childItem ? childItem->parent() : 0;
1113 if ( !parentItem || parentItem == rootItem() )
1114 return QModelIndex();
1116 return createIndex( parentItem->position(), 0, parentItem );
1120 \brief Get number of data columns.
1121 \param parent parent model index (not used)
1122 \return data columns number
1125 int SUIT_TreeModel::columnCount( const QModelIndex& /*parent*/ ) const
1127 return myColumns.size();
1131 \brief Get number of data rows (children of the specified model index).
1132 \param parent parent model index
1133 \return data rows (children) number
1136 int SUIT_TreeModel::rowCount( const QModelIndex& parent ) const
1138 // Commented by rnv in the frame of the
1139 // "20830: EDF 1357 GUI : Hide/Show Icon" imp
1140 // if ( parent.column() > 0 )
1143 TreeItem* parentItem = treeItem( parent );
1145 return parentItem ? parentItem->childCount() : 0;
1149 \brief Get data object by the specified model index.
1150 \param index model index
1151 \return data object corresponding to the model index
1153 SUIT_DataObject* SUIT_TreeModel::object( const QModelIndex& index ) const
1155 return object( treeItem( index ) );
1159 \brief Get model index by the specified data object.
1160 \param obj data object
1161 \param column data object column
1164 QModelIndex SUIT_TreeModel::index( const SUIT_DataObject* obj, int column ) const
1166 if ( obj == root() )
1167 return QModelIndex();
1169 TreeItem* item = treeItem( obj );
1171 return item ? createIndex( item->position(), column, item ) : QModelIndex();
1175 \brief Get 'auto-delete data tree' flag value.
1176 \return 'auto-delete data tree' flag value
1177 \sa setAutoDeleteTree()
1179 bool SUIT_TreeModel::autoDeleteTree() const
1181 return myAutoDeleteTree;
1185 \brief Set 'auto-delete data tree' flag value.
1187 If this flag is set to \c true, the data tree is deleted when
1188 the tree model is destroyed. Default value for this flag is \c false.
1190 \param on 'auto-delete data tree' flag value
1191 \sa autoDeleteTree()
1193 void SUIT_TreeModel::setAutoDeleteTree( const bool on )
1195 myAutoDeleteTree = on;
1199 \brief Get 'auto-update tree' flag value.
1200 \return 'auto-update tree' flag value
1201 \sa setAutoUpdate(), updateTree()
1203 bool SUIT_TreeModel::autoUpdate() const
1205 return myAutoUpdate;
1209 \brief Set 'auto-update tree' flag value.
1211 If this flag is set to \c true (by default), the model is updated
1212 automatically when data tree is changed.
1214 \param on 'auto-update tree' flag value
1215 \sa autoUpdate(), updateTree()
1217 void SUIT_TreeModel::setAutoUpdate( const bool on )
1219 if ( myAutoUpdate == on )
1222 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1223 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1224 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1225 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1226 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
1227 this, SLOT( onModified( SUIT_DataObject* ) ) );
1230 if ( myAutoUpdate ) {
1231 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1232 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1233 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1234 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1235 SUIT_DataObject::connect( SIGNAL( modified( SUIT_DataObject* ) ),
1236 this, SLOT( onModified( SUIT_DataObject* ) ) );
1243 \brief Get 'updateModified' flag value.
1244 \return 'updateModified' flag value
1246 bool SUIT_TreeModel::updateModified() const
1248 return myUpdateModified;
1251 \brief Set 'updateModified' flag value.
1252 \param on 'updateModified' flag value
1254 void SUIT_TreeModel::setUpdateModified(const bool on)
1256 myUpdateModified=on;
1260 \brief Check if the specified column supports custom sorting.
1261 \param column column index on which data is being sorted
1262 \return \c true if column requires custom sorting
1265 bool SUIT_TreeModel::customSorting( const int column ) const
1267 return root() ? root()->customSorting( column ) : false;
1270 void SUIT_TreeModel::forgetObject( const SUIT_DataObject* obj )
1272 removeItem( treeItem( obj ) );
1276 \brief Compares two model indexes for the sorting purposes.
1278 This method is called only for those columns for which customSorting()
1279 method returns \c true.
1281 \param left first index to compare
1282 \param right second index to compare
1283 \return result of the comparison
1286 bool SUIT_TreeModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
1288 QVariant ldata = data( left );
1289 QVariant rdata = data( right );
1290 return root() ? root()->compare( ldata, rdata, left.column() ) : false;
1294 \brief Get item delegate for the model.
1295 \return new item delegate
1297 QAbstractItemDelegate* SUIT_TreeModel::delegate() const
1299 return new SUIT_ItemDelegate( const_cast<SUIT_TreeModel*>( this ) );
1303 void SUIT_TreeModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index) {
1304 int obj_group_id = obj->groupId();
1305 const ColumnInfo& inf = myColumns[index.column()];
1308 if( inf.myIds.contains( 0 ) )
1310 if( inf.myIds.contains( obj_group_id ) )
1311 id = inf.myIds[obj_group_id];
1312 emit clicked(obj, id);
1316 \brief Update tree model.
1318 Call this method when data tree is changed outside the model.
1319 If the 'auto-update' flag is set to \c true, the model
1320 is updated automatically when the data tree is changed.
1322 \param index starting index for the updating
1325 void SUIT_TreeModel::updateTree( const QModelIndex& index )
1327 updateTree( object( index ) );
1331 void SUIT_TreeModel::updateTreeModel(SUIT_DataObject* obj,TreeItem* item)
1335 int nobjchild=obj->childCount();
1336 SUIT_DataObject* sobj=obj->childObject(kobj);
1337 TreeItem* sitem = item->child(kitem);
1339 while(kobj < nobjchild)
1344 sitem=createItemAtPos(sobj,item,kitem);
1345 updateTreeModel(sobj,sitem);
1348 sobj=obj->childObject(kobj);
1349 sitem = item->child(kitem);
1351 else if(sitem->dataObject() != sobj)
1357 sitem = item->child(kitem);
1362 sitem=createItemAtPos(sobj,item,kitem);
1363 updateTreeModel(sobj,sitem);
1366 sobj=obj->childObject(kobj);
1367 sitem = item->child(kitem);
1372 //obj and item are synchronised : go to next ones
1373 updateTreeModel(sobj,sitem);
1374 if(sobj->modified()) updateItem(sitem, true);
1378 sobj=obj->childObject(kobj);
1379 sitem = item->child(kitem);
1382 //remove remaining items
1383 for(int i = item->childCount(); i > kitem;i--)
1385 sitem = item->child(i-1);
1391 \brief Update tree model.
1393 Call this method when data tree is changed outside the model.
1394 If the 'auto-update' flag is set to \c true, the model
1395 is updated automatically when the data tree is changed.
1397 \param obj starting data object for the updating
1400 void SUIT_TreeModel::updateTree( SUIT_DataObject* obj )
1405 else if ( obj->root() != root() )
1408 if(updateModified())
1410 updateTreeModel(obj,treeItem( obj ));
1414 synchronize<ObjPtr,ItemPtr,SUIT_TreeModel::TreeSync>( obj,
1416 SUIT_TreeModel::TreeSync( this ) );
1418 emit modelUpdated();
1422 \brief Initialize tree model.
1424 void SUIT_TreeModel::initialize()
1426 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1427 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1428 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1429 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1430 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
1431 this, SLOT( onModified( SUIT_DataObject* ) ) );
1432 if ( autoUpdate() ) {
1433 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1434 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1435 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1436 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1437 SUIT_DataObject::connect( SIGNAL( modified( SUIT_DataObject* ) ),
1438 this, SLOT( onModified( SUIT_DataObject* ) ) );
1441 myItems.clear(); // ????? is it really necessary
1444 myRootItem = new TreeItem( 0 );
1446 registerColumn( 0, QObject::tr( "NAME_COLUMN" ), SUIT_DataObject::NameId );
1448 QString visCol = QObject::tr( "VISIBILITY_COLUMN" );
1449 registerColumn( 0, visCol, SUIT_DataObject::VisibilityId );
1451 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1452 setColumnIcon( visCol, resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ));
1453 setHeaderFlags( visCol, Qtx::ShowIcon);
1459 \brief Get root tree item.
1460 \return root tree item
1462 SUIT_TreeModel::TreeItem* SUIT_TreeModel::rootItem() const
1468 \brief Get tree item corresponding to the specified model index.
1469 \param index model index
1470 \return tree item or root item if index is invalid
1472 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const QModelIndex& index ) const
1474 return index.isValid() ? static_cast<TreeItem*>( index.internalPointer() ) : rootItem();
1478 \brief Get tree item corresponding to the specified data object.
1479 \param obj data object
1480 \return tree item or 0 if there is no tree item corresponding to \a obj
1482 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const SUIT_DataObject* obj ) const
1486 if ( obj == root() )
1488 else if ( myItems.contains( const_cast<SUIT_DataObject*>( obj ) ) )
1489 item = myItems[ const_cast<SUIT_DataObject*>( obj ) ];
1495 \brief Get data object corresponding to the specified tree item.
1496 \param item tree item
1497 \return data object or 0 if there is no data object corresponding to \a item
1499 SUIT_DataObject* SUIT_TreeModel::object( const SUIT_TreeModel::TreeItem* item ) const
1501 if ( item == rootItem() )
1504 SUIT_DataObject* obj = item ? item->dataObject() : 0;
1505 return myItems.contains( obj ) ? obj : 0;
1509 \brief Get unique object identifier
1511 Object identifier is customized via the Qtx::IdType custom data
1513 \param index model index
1514 \return object identifier or null string if it isn't specified
1515 \sa SUIT_DataObject::customData()
1517 QString SUIT_TreeModel::objectId( const QModelIndex& index ) const
1520 if ( index.isValid() ) {
1521 SUIT_DataObject* obj = object( index );
1523 int anId = obj->customData( Qtx::IdType ).toInt();
1524 objId = data( createIndex( index.row(), anId, index.internalPointer() ) ).toString();
1531 \brief Create an item corresponding to the data object.
1532 \param obj source data object
1533 \param parent parent tree item
1534 \param after tree item after which new item should be inserted
1535 \return created tree item or 0 if item could not be created
1537 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItem( SUIT_DataObject* obj,
1538 SUIT_TreeModel::TreeItem* parent,
1539 SUIT_TreeModel::TreeItem* after )
1544 SUIT_DataObject* parentObj = object( parent );
1545 QModelIndex parentIdx = index( parentObj );
1547 SUIT_DataObject* afterObj = after ? object( after ) : 0;
1548 int row = afterObj ? afterObj->position() + 1 : 0;
1550 beginInsertRows( parentIdx, row, row );
1552 myItems[ obj ] = new TreeItem( obj, parent, after );
1554 for(int pos=row;pos < parent->childCount();pos++)
1555 parent->child(pos)->setPosition(pos);
1559 obj->setModified(false);
1561 return myItems[ obj ];
1565 \brief Create an item corresponding to the data object.
1566 \param obj source data object
1567 \param parent parent tree item
1568 \param pos tree item position into which new item should be inserted
1569 \return created tree item or 0 if item could not be created
1571 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItemAtPos( SUIT_DataObject* obj,
1572 SUIT_TreeModel::TreeItem* parent,
1578 SUIT_DataObject* parentObj = object( parent );
1579 QModelIndex parentIdx = index( parentObj );
1582 SUIT_TreeModel::TreeItem* after = pos>0 ? parent->child(pos-1) : 0 ;
1584 beginInsertRows( parentIdx, row, row );
1586 SUIT_TreeModel::TreeItem* item = new TreeItem( obj, parent, after );
1587 myItems[ obj ] = item;
1589 for(int ppos=row;ppos < parent->childCount();ppos++)
1590 parent->child(ppos)->setPosition(ppos);
1594 obj->setModified(false);
1600 \brief Update tree item.
1601 \param item tree item to be updated
1602 \param emitLayoutChanged if signal about changed layout should be emitted
1604 void SUIT_TreeModel::updateItem( SUIT_TreeModel::TreeItem* item, bool emitLayoutChanged )
1609 SUIT_DataObject* obj = object( item );
1613 // update all columns corresponding to the given data object
1614 /*To avoid crashes we should update any persistent model indexes before emitting layoutChanged(). In other words, when the structure changes:
1615 - emit layoutAboutToBeChanged
1616 - Remember the QModelIndex that will change
1617 - call changePersistentIndex()
1618 - emit layoutChanged
1621 emit layoutAboutToBeChanged();
1623 // Remember the QModelIndex that will change
1624 QModelIndexList fromIndexes;
1625 QModelIndexList toIndexes;
1626 for (int i = 0; i < columnCount() - 1; ++i) {
1627 fromIndexes.append( index( obj, i ));
1628 toIndexes.append(QModelIndex());
1630 changePersistentIndexList(fromIndexes, toIndexes); // Limitation: can lead to loss of selection
1632 emit dataChanged( toIndexes.first(), toIndexes.last() );
1633 obj->setModified(false);
1634 if ( emitLayoutChanged )
1635 emit layoutChanged();
1639 \brief Remove tree item (recursively).
1640 \param item tree item to be removed
1642 void SUIT_TreeModel::removeItem( SUIT_TreeModel::TreeItem* item )
1647 // Remove list view items from <myItems> recursively for all children.
1648 // Otherwise, "delete item" line below will destroy all item's children,
1649 // and <myItems> will contain invalid pointers
1650 while( item->childCount() )
1651 removeItem( item->child( 0 ) );
1653 SUIT_DataObject* obj = object( item );
1655 // Warning! obj can be deleted at this point!
1657 TreeItem* parent=item->parent();
1658 SUIT_DataObject* parentObj = object( parent );
1659 QModelIndex parentIdx = index( parentObj, 0 );
1660 int row = item->position();
1662 beginRemoveRows( parentIdx, row, row );
1663 myItems.remove( obj );
1665 if ( obj == root() )
1669 parent->removeChild( item );
1670 for(int pos=row;pos < parent->childCount();pos++)
1671 parent->child(pos)->setPosition(pos);
1680 \brief Called when the data object is inserted to the tree.
1681 \param object data object being inserted
1682 \param parent parent data object
1684 void SUIT_TreeModel::onInserted( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1687 updateTree( parent );
1691 \brief Called when the data object is removed from the tree.
1692 \param object data object being removed
1693 \param parent parent data object
1695 void SUIT_TreeModel::onRemoved( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1698 updateTree( parent );
1702 \brief Called when the data object is modified. TreeSync is not used here for maximum efficiency.
1703 It is assumed that it is up to the application to decide when its data objects are modified.
1704 \param obj data object that has been modified
1706 void SUIT_TreeModel::onModified( SUIT_DataObject* obj )
1710 QModelIndex firstIdx = index( obj, 0 );
1711 QModelIndex lastIdx = index( obj, columnCount() - 1 );
1712 emit dataChanged( firstIdx, lastIdx );
1713 obj->setModified(false);
1718 \brief Drag and Drop support.
1720 QStringList SUIT_TreeModel::mimeTypes() const
1723 types << "application/vnd.text.list";
1728 \brief Called when the data objects are exported(dragged) from the tree.
1729 \param indexes the list of exported objects
1731 QMimeData* SUIT_TreeModel::mimeData( const QModelIndexList& indexes ) const
1733 QMimeData* mimeData = new QMimeData();
1734 QByteArray encodedData;
1736 QDataStream stream( &encodedData, QIODevice::WriteOnly );
1738 foreach ( QModelIndex index, indexes ) {
1739 QString id = objectId( index );
1740 // we have to check only 0 column in order to avoid repeating items in the drag object
1741 // - QTreeView tries to drag indices for all visible columns
1742 if ( index.isValid() && index.column() == 0 && !id.isEmpty() )
1746 mimeData->setData( "application/vnd.text.list", encodedData );
1750 bool SUIT_TreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action,
1751 int row, int column, const QModelIndex& parent )
1753 if ( action == Qt::IgnoreAction )
1754 // do nothing with data
1757 if ( !data->hasFormat( "application/vnd.text.list" ) )
1758 // not supported data dropped
1761 if ( !parent.isValid() )
1762 // dropping into the top level of the model is not allowed
1765 // get parent object
1766 SUIT_DataObject* pobj = object( parent );
1771 // decode mime data and collect data objects being dropped
1772 QByteArray encodedData = data->data( "application/vnd.text.list" );
1773 QDataStream stream( &encodedData, QIODevice::ReadOnly );
1775 DataObjectList objects;
1777 while ( !stream.atEnd() ) {
1780 if ( !id.isEmpty() && searcher() ) {
1781 SUIT_DataObject* obj = searcher()->findObject( id );
1782 if ( obj ) objects << obj;
1787 emit dropped( objects, pobj, row, action );
1789 // return true if there's any to drop
1790 return !objects.isEmpty();
1794 \class SUIT_ProxyModel
1795 \brief Proxy model which can be used above the SUIT_TreeModel class
1796 to enable custom sorting/filtering of the data.
1798 The SUIT_TreeModel class does not support custom sorting/filtering of the data.
1799 To use these features, the SUIT_ProxyModel class can be used as top-level
1800 wrapper for the SUIT_DataObject-based data tree model.
1805 \param parent parent object
1807 SUIT_ProxyModel::SUIT_ProxyModel( QObject* parent )
1808 : QSortFilterProxyModel( parent ),
1809 mySortingEnabled( true )
1811 SUIT_TreeModel* model = new SUIT_TreeModel( this );
1812 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1813 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL(clicked( SUIT_DataObject*, int ) ) );
1814 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1815 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1816 setSourceModel( model );
1817 setDynamicSortFilter( true );
1822 \param root root data object
1823 \param parent parent object
1825 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_DataObject* root, QObject* parent )
1826 : QSortFilterProxyModel( parent ),
1827 mySortingEnabled( true )
1829 SUIT_TreeModel* model = new SUIT_TreeModel( root, this );
1830 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1831 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1832 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1833 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1834 setSourceModel( model );
1835 setDynamicSortFilter( true );
1840 \param model tree model
1841 \param parent parent object
1843 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_AbstractModel* model, QObject* parent )
1844 : QSortFilterProxyModel( parent ),
1845 mySortingEnabled( true )
1847 connect( *model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1848 connect( *model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1849 connect( *model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1850 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1851 setSourceModel( *model );
1852 setDynamicSortFilter( true );
1858 SUIT_ProxyModel::~SUIT_ProxyModel()
1863 \brief Get data tree root object.
1864 \return data tree root
1867 SUIT_DataObject* SUIT_ProxyModel::root() const
1869 return treeModel() ? treeModel()->root() : 0;
1873 \brief Set data tree root object.
1874 \param r new data tree root
1877 void SUIT_ProxyModel::setRoot( SUIT_DataObject* r )
1880 treeModel()->setRoot( r );
1884 \brief Get data object by the specified model index.
1885 \param index model index
1886 \return data object corresponding to the model index
1888 SUIT_DataObject* SUIT_ProxyModel::object( const QModelIndex& index ) const
1890 return treeModel() ? treeModel()->object( mapToSource( index ) ) : 0;
1894 \brief Get model index by the specified data object.
1895 \param obj data object
1896 \param column data object column
1899 QModelIndex SUIT_ProxyModel::index( const SUIT_DataObject* obj, int column ) const
1901 return treeModel() ? mapFromSource( treeModel()->index( obj, column ) ) : QModelIndex();
1905 \brief Get 'auto-delete data tree' flag value.
1906 \return 'auto-delete data tree' flag value
1907 \sa setAutoDeleteTree()
1909 bool SUIT_ProxyModel::autoDeleteTree() const
1911 return treeModel() ? treeModel()->autoDeleteTree() : false;
1915 \brief Set 'auto-delete data tree' flag value.
1917 If this flag is set to \c true, the data tree is deleted when
1918 the tree model is destroyed. Default value for this flag is \c false.
1920 \param on 'auto-delete data tree' flag value
1921 \sa autoDeleteTree()
1923 void SUIT_ProxyModel::setAutoDeleteTree( const bool on )
1926 treeModel()->setAutoDeleteTree( on );
1930 \brief Get 'auto-update tree' flag value.
1931 \return 'auto-update tree' flag value
1932 \sa setAutoUpdate(), updateTree()
1934 bool SUIT_ProxyModel::autoUpdate() const
1936 return treeModel() ? treeModel()->autoUpdate() : false;
1940 \brief Get 'updateModified' flag value.
1941 \return 'updateModified' flag value
1943 bool SUIT_ProxyModel::updateModified() const
1945 return treeModel() ? treeModel()->updateModified() : false;
1948 \brief Set 'updateModified' flag value.
1950 If this flag is set to \c true (default=false), the model is updated by updateTreeModel that
1951 uses the isModified flag to update only modified objects
1953 \param on 'updateModified' flag value
1955 void SUIT_ProxyModel::setUpdateModified( const bool on )
1958 treeModel()->setUpdateModified( on );
1962 \brief Set 'auto-update tree' flag value.
1964 If this flag is set to \c true (by default), the model is updated
1965 automatically when data tree is changed.
1967 \param on 'auto-update tree' flag value
1968 \sa autoUpdate(), updateTree()
1970 void SUIT_ProxyModel::setAutoUpdate( const bool on )
1973 treeModel()->setAutoUpdate( on );
1977 \brief Check if sorting is enabled.
1978 \return \c true if sorting is enabled
1979 \sa setSortingEnabled()
1981 bool SUIT_ProxyModel::isSortingEnabled() const
1983 return mySortingEnabled;
1986 SUIT_DataSearcher* SUIT_ProxyModel::searcher() const
1988 return treeModel() ? treeModel()->searcher() : 0;
1991 void SUIT_ProxyModel::setSearcher( SUIT_DataSearcher* s )
1993 if ( treeModel() ) treeModel()->setSearcher( s );
1997 \brief Get item delegate for the model.
1998 \return new item delegate
2000 QAbstractItemDelegate* SUIT_ProxyModel::delegate() const
2002 return treeModel() ? treeModel()->delegate() : 0;
2006 \brief Update tree model.
2008 Call this method when data tree is changed outside the model.
2009 If the 'auto-update' flag is set to \c true, the model
2010 is updated automatically when the data tree is changed.
2012 \param index starting index for the updating
2015 void SUIT_ProxyModel::updateTree( const QModelIndex& index )
2018 treeModel()->updateTree( mapToSource( index ) );
2022 \brief Update tree model.
2024 Call this method when data tree is changed outside the model.
2025 If the 'auto-update' flag is set to \c true, the model
2026 is updated automatically when the data tree is changed.
2028 \param obj starting data object for the updating
2031 void SUIT_ProxyModel::updateTree( SUIT_DataObject* obj )
2034 treeModel()->updateTree( obj );
2037 void SUIT_ProxyModel::forgetObject( const SUIT_DataObject* obj )
2040 treeModel()->forgetObject( obj );
2044 \brief Compares two model indexes for the sorting purposes.
2045 \param left first index to compare
2046 \param right second index to compare
2047 \return result of the comparison
2049 bool SUIT_ProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
2051 if ( !isSortingEnabled() && left.isValid() && right.isValid() ) {
2052 return left.row() < right.row();
2054 if ( treeModel() && treeModel()->customSorting( left.column() ) ) {
2055 return treeModel()->lessThan( left, right );
2057 return QSortFilterProxyModel::lessThan( left, right );
2061 \brief Check if the specified column supports custom sorting.
2062 \param column column index on which data is being sorted
2063 \return \c true if column requires custom sorting
2066 bool SUIT_ProxyModel::customSorting( const int column ) const
2068 return treeModel() ? treeModel()->customSorting( column ) : false;
2072 \brief Enable/disable sorting.
2073 \param enabled new flag state
2074 \sa isSortingEnabled()
2076 void SUIT_ProxyModel::setSortingEnabled( bool enabled )
2078 mySortingEnabled = enabled;
2083 \brief Get tree model.
2086 SUIT_AbstractModel* SUIT_ProxyModel::treeModel() const
2088 return dynamic_cast<SUIT_AbstractModel*>( sourceModel() );
2093 \param sourceRow row index of the source data model
2094 \param sourceParent parent model index of the source data model
2095 \return \c true if the specified row should be filtered out (i.e. not displayed) or \c false otherwise
2097 bool SUIT_ProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
2099 SUIT_DataObject* o = treeModel()->object( sourceModel()->index( sourceRow, 0, sourceParent ) );
2100 SUIT_DataObject* p = o ? o->parent() : 0;
2101 return ( !p || p->expandable() ) && o && o->isVisible();
2105 \brief Register new column in the model
2106 \param group_id - unique data object identificator allowing the classification of objects
2107 \param name - translated column name
2108 \param custom_id - custom column id that should be passed into method SUIT_DataObject::data()
2110 void SUIT_ProxyModel::registerColumn( const int group_id, const QString& name, const int custom_id )
2113 treeModel()->registerColumn( group_id, name, custom_id );
2117 \brief Remove column from the model
2119 Please take into account that column is removed only for given group_id, it means
2120 that information of data objects with such group_id won't be shown.
2121 If there is not any registered group_id for this column after removing, the column will be hidden
2122 otherwise it continue to be shown
2124 \param group_id - unique data object identificator allowing the classification of objects
2125 \param name - translated column name
2127 void SUIT_ProxyModel::unregisterColumn( const int group_id, const QString& name )
2130 treeModel()->unregisterColumn( group_id, name );
2134 \brief Change column icon.
2136 \param name - column name
2137 \param icon - new icon of the specified column
2139 void SUIT_ProxyModel::setColumnIcon( const QString& name, const QPixmap& icon )
2142 treeModel()->setColumnIcon( name, icon );
2146 \brief Get column icon.
2148 \param name - column name
2149 \return icon of the specified column
2151 QPixmap SUIT_ProxyModel::columnIcon( const QString& name ) const
2153 return treeModel() ? treeModel()->columnIcon( name ) : QPixmap();
2157 \brief Change appropriate status
2159 Appropriate status determines if the column should appear in the tree view header popup menu
2160 (to show/hide the column).
2162 If appropriate status is not specified yet, the \c Shown value is taken,
2163 it means that column should be always visible.
2165 \param name - column name
2166 \param appr - new appropriate status
2168 void SUIT_ProxyModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
2171 treeModel()->setAppropriate( name, appr );
2175 \brief Check if the column should appear in the tree view header popup menu
2176 (to show/hide the column).
2178 Default implementation (if appropriate status is not specified yet)
2179 returns \c Shown, it means that column should be always visible.
2181 \param name - column name
2182 \return appropriate status
2184 Qtx::Appropriate SUIT_ProxyModel::appropriate( const QString& name ) const
2186 return treeModel() ? treeModel()->appropriate( name ) : Qtx::Shown;
2190 \brief Set header flags.
2192 These flags allow show in the header of the column text (name of the column),
2193 icon or both text and icon.
2195 \param name - column name
2196 \param flags - header flags
2199 void SUIT_ProxyModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
2202 treeModel()->setHeaderFlags(name, flags);
2206 \brief Get the header flags.
2208 These flags allow show in the header of the column text (name of the column),
2209 icon or both text and icon.
2211 \param name - column name
2212 \return header flags
2214 Qtx::HeaderViewFlags SUIT_ProxyModel::headerFlags( const QString& name ) const
2216 return treeModel() ? treeModel()->headerFlags( name ) : Qtx::ShowAll;
2220 \brief Set visibility state of the object.
2222 \param id - column name
2223 \param state - visible state
2224 \param emitChanged - if set to false, blocks dataChanged() signal, this can be used to
2225 prevent emitting dataChanged() several times for the same data object
2227 void SUIT_ProxyModel::setVisibilityState(const QString& id, Qtx::VisibilityState state, bool emitChanged ) {
2229 treeModel()->setVisibilityState(id,state,emitChanged);
2233 \brief Set visibility state for all objects.
2235 \param id - column name
2236 \param state - visible state
2238 void SUIT_ProxyModel::setVisibilityStateForAll(Qtx::VisibilityState state)
2241 treeModel()->setVisibilityStateForAll(state);
2245 \brief Get visibility state of the object.
2247 \param id - column name
2248 \return visible state
2250 Qtx::VisibilityState SUIT_ProxyModel::visibilityState(const QString& id) const
2252 return treeModel() ? treeModel()->visibilityState(id) : Qtx::UnpresentableState;
2255 void SUIT_ProxyModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index)
2258 treeModel()->emitClicked(obj,index);
2262 \class SUIT_ItemDelegate
2263 \brief An SUIT_DataObject-based item delegate class.
2265 This class can be used to render the SUIT_DataObject-based item
2266 in the widgets like QTreeView and others.
2267 Refer to the Qt 4 documentation, model/view architecture
2268 section for more details).
2273 \param parent parent object
2275 SUIT_ItemDelegate::SUIT_ItemDelegate( QObject* parent )
2276 : QItemDelegate( parent )
2281 \brief Render the item in the widget.
2283 Customizes the item colors for the specific roles.
2285 \param painter painter
2286 \param option painting option
2287 \param index model index being rendered
2289 void SUIT_ItemDelegate::paint( QPainter* painter,
2290 const QStyleOptionViewItem& option,
2291 const QModelIndex& index ) const
2293 QStyleOptionViewItem opt = option;
2294 if ( index.isValid() ) {
2295 // Note: we check into account only custom roles; other roles are process
2296 // correctly by the QItemDelegate class
2297 QVariant val = index.data( SUIT_TreeModel::BaseColorRole );
2298 if ( val.isValid() && val.value<QColor>().isValid() ) {
2299 QColor aBase = val.value<QColor>();
2300 aBase.setAlpha( 0 );
2301 opt.palette.setBrush( QPalette::Base, val.value<QColor>() );
2303 val = index.data( SUIT_TreeModel::TextColorRole );
2304 if ( val.isValid() && val.value<QColor>().isValid() )
2305 opt.palette.setBrush( QPalette::Text, val.value<QColor>() );
2306 val = index.data( SUIT_TreeModel::HighlightRole );
2307 if ( val.isValid() && val.value<QColor>().isValid() )
2308 opt.palette.setBrush( QPalette::Highlight, val.value<QColor>() );
2309 val = index.data( SUIT_TreeModel::HighlightedTextRole );
2310 if ( val.isValid() && val.value<QColor>().isValid() )
2311 opt.palette.setBrush( QPalette::HighlightedText, val.value<QColor>() );
2313 QItemDelegate::paint( painter, opt, index );
2316 QSize SUIT_ItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
2318 QSize size = QItemDelegate::sizeHint ( option, index );
2319 #if QT_VERSION >= 0x040500
2320 size.setHeight( size.height() + 1 );