1 // Copyright (C) 2007-2012 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* ) ) );
493 \brief Register new column in the model
494 \param group_id - unique data object group identificator
495 \param name - translated column name
496 \param custom_id - custom column id that should be passed into method SUIT_DataObject::data()
498 void SUIT_TreeModel::registerColumn( const int group_id, const QString& name, const int custom_id )
501 for ( int i=0, n=myColumns.size(); i<n && !found; i++ ) {
502 if ( name == myColumns[i].myName ) {
503 myColumns[i].myIds.insert( group_id, custom_id );
510 inf.myIds.insert( group_id, custom_id );
511 inf.myAppropriate = Qtx::Shown;
512 inf.myHeaderFlags = Qtx::ShowAll;
513 int n = myColumns.size();
514 myColumns.resize( n+1 );
521 \brief Remove column from the model
523 Please take into account that column is removed only for given group_id, it means
524 that information of data objects with such group_id won't be shown.
525 If there is not any registered group_id for this column after removing, the column will be hidden
526 otherwise it continue to be shown
528 \param group_id - unique data object identificator allowing the classification of objects
529 \param name - translated column name
531 void SUIT_TreeModel::unregisterColumn( const int group_id, const QString& name )
533 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
534 if ( myColumns[i].myName == name ) {
535 myColumns[i].myIds.remove( group_id );
536 if ( myColumns[i].myIds.isEmpty() ) {
537 myColumns.remove( i );
546 \brief Change column icon.
548 \param name - column name
549 \param icon - new icon of the specified column
551 void SUIT_TreeModel::setColumnIcon( const QString& name, const QPixmap& icon )
553 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
554 if ( myColumns[i].myName == name ) {
555 myColumns[i].myIcon = icon;
562 \brief Get column icon.
564 \param name - column name
565 \return icon of the specified column
567 QPixmap SUIT_TreeModel::columnIcon( const QString& name ) const
570 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
571 if ( myColumns[i].myName == name ) {
572 res = myColumns[i].myIcon;
580 \brief Change appropriate status
582 Appropriate status determines if the column should appear in the tree view header popup menu
583 (to show/hide the column).
585 If appropriate status is not specified yet, the \c Shown value is taken,
586 it means that column should be always visible.
588 \param name - column name
589 \param appr - new appropriate status
591 void SUIT_TreeModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
593 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
594 if ( myColumns[i].myName == name && myColumns[i].myAppropriate != appr ) {
595 myColumns[i].myAppropriate = appr;
596 emit headerDataChanged( Qt::Horizontal, i, i );
603 \brief Check if the column should appear in the tree view header popup menu
604 (to show/hide the column).
606 Default implementation (if appropriate status is not specified yet)
607 returns \c Shown, it means that column should be always visible.
609 \param name - column name
610 \return appropriate status
612 Qtx::Appropriate SUIT_TreeModel::appropriate( const QString& name ) const
614 Qtx::Appropriate appr = Qtx::Shown;
615 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
616 if ( myColumns[i].myName == name ) {
617 appr = myColumns[i].myAppropriate;
626 \brief Set header flags.
628 These flags allow show in the header of the column text (name of the column),
629 icon or both text and icon.
631 \param name - column name
632 \param flags - header flags
635 void SUIT_TreeModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
637 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
638 if ( myColumns[i].myName == name && myColumns[i].myHeaderFlags != flags ) {
639 myColumns[i].myHeaderFlags = flags;
640 emit headerDataChanged( Qt::Horizontal, i, i );
647 \brief Get the header flags.
649 These flags allow show in the header of the column text (name of the column),
650 icon or both text and icon.
652 \param name - column name
655 Qtx::HeaderViewFlags SUIT_TreeModel::headerFlags( const QString& name ) const
657 Qtx::HeaderViewFlags flags;
658 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
659 if ( myColumns[i].myName == name ) {
660 flags = myColumns[i].myHeaderFlags;
668 \brief Set visibility state of the object.
670 \param id - column name
671 \param state - visible state
673 void SUIT_TreeModel::setVisibilityState( const QString& id, Qtx::VisibilityState state )
675 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
676 if ( it != myVisibilityMap.end() && it.value() == state )
679 bool needSignal = false;
680 if ( state != Qtx::UnpresentableState ) {
681 myVisibilityMap.insert( id, state );
685 needSignal = myVisibilityMap.remove( id ) > 0;
690 SUIT_DataObject* o = searcher()->findObject( id );
691 if ( o ) lst << index( o );
694 lst = match( index( 0, root()->customData( Qtx::IdType ).toInt() ), DisplayRole, id, 1, Qt::MatchExactly | Qt::MatchRecursive );
696 if ( !lst.isEmpty() ) {
697 QModelIndex idx = index( lst.first().row(), SUIT_DataObject::VisibilityId, lst.first().parent() );
698 emit dataChanged( idx, idx );
704 \brief Set visibility state for all objects.
706 \param id - column name
707 \param state - visible state
709 void SUIT_TreeModel::setVisibilityStateForAll( Qtx::VisibilityState state )
711 if ( state != Qtx::UnpresentableState ) {
712 VisibilityMap::ConstIterator it = myVisibilityMap.begin();
713 while ( it != myVisibilityMap.end() ) {
714 if ( it.value() != state )
715 setVisibilityState( it.key(), state );
720 QList<QString> anIds = myVisibilityMap.keys();
721 myVisibilityMap.clear();
722 QList<QString>::ConstIterator it = anIds.begin();
723 while ( it != anIds.end() ) {
726 SUIT_DataObject* o = searcher()->findObject( *it );
727 if ( o ) lst << index( o );
730 lst = match( index( 0, root()->customData( Qtx::IdType ).toInt() ), DisplayRole, (*it), 1, Qt::MatchExactly | Qt::MatchRecursive );
732 if ( !lst.isEmpty() ) {
733 QModelIndex idx = index( lst.first().row(), SUIT_DataObject::VisibilityId ,lst.first().parent() );
734 emit dataChanged( idx, idx );
742 \brief Get visibility state of the object.
744 \param id - column name
745 \return visible state
747 Qtx::VisibilityState SUIT_TreeModel::visibilityState( const QString& id ) const
749 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
750 return it != myVisibilityMap.end() ? it.value() : Qtx::UnpresentableState;
754 \brief Get data tree root object.
755 \return data tree root
758 SUIT_DataObject* SUIT_TreeModel::root() const
764 \brief Set data tree root object.
765 \param r new data tree root
768 void SUIT_TreeModel::setRoot( SUIT_DataObject* r )
773 if ( autoDeleteTree() ) {
774 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
775 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
776 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
777 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
789 \brief Get data for the specified model index and data role.
790 \param index model index
791 \param role data role
792 \return requested data
795 QVariant SUIT_TreeModel::data( const QModelIndex& index, int role ) const
797 if ( !index.isValid() )
800 SUIT_DataObject* obj = object( index );
807 int obj_group_id = obj->groupId();
808 const ColumnInfo& inf = myColumns[index.column()];
811 if( inf.myIds.contains( 0 ) )
813 if( inf.myIds.contains( obj_group_id ) )
814 id = inf.myIds[obj_group_id];
824 // data object text for the specified column
825 val = obj->text( id );
828 // data object text for the specified column (for editor)
829 val = obj->text( id );
831 case DecorationRole: {
833 if ( id == SUIT_DataObject::VisibilityId ) {
834 // for visibility column, icon is defined specifically (using data object id)
835 QString objId = objectId( index );
836 if ( myVisibilityMap.contains( objId ) ) {
837 // visibility status is defined -> return proper icon
838 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
839 val = ( myVisibilityMap.value( objId ) == Qtx::ShownState ) ?
840 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ) :
841 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_INVISIBLE" ) );
844 // visibility status is undefined -> no icon
849 // for other columns get icon from the object
850 val = obj->icon( id );
855 // data object tooltip for the specified column
856 val = obj->toolTip( id );
859 // data object status tip for the specified column
860 val = obj->statusTip( id );
863 // data object what's this info for the specified column
864 val = obj->whatsThis( id );
867 // data object font for the specified column
868 val = obj->font( id );
870 case TextAlignmentRole:
871 // data object text alignment for the specified column
872 val = obj->alignment( id );
875 // data background color for the specified column
876 c = obj->color( SUIT_DataObject::Background, id );
877 if( !c.isValid() ) // default value
878 c = QApplication::palette().color( QPalette::Base );
883 // data foreground (text) color for the specified column
884 c = obj->color( SUIT_DataObject::Foreground, id );
885 if( !c.isValid() ) // default value
886 c = QApplication::palette().color( QPalette::Foreground );
890 // editor background color for the specified column
891 c = obj->color( SUIT_DataObject::Base, id );
892 if( !c.isValid() ) // default value
893 c = QApplication::palette().color( QPalette::Base );
897 // editor foreground (text) color for the specified column
898 c = obj->color( SUIT_DataObject::Text, id );
899 if( !c.isValid() ) // default value
900 c = QApplication::palette().color( QPalette::Text );
904 // adta object highlighted background color for the specified column
905 c = obj->color( SUIT_DataObject::Highlight, id );
906 if( !c.isValid() ) // default value
907 c = QApplication::palette().color( QPalette::Highlight );
910 case HighlightedTextRole:
911 // data object highlighted foreground (text) color for the specified column
912 c = obj->color( SUIT_DataObject::HighlightedText, id );
913 if( !c.isValid() ) // default value
914 c = QApplication::palette().color( QPalette::HighlightedText );
918 // data object checked state for the specified column
919 // NOTE! three-state check is not supported currently
920 if( obj->isCheckable( id ) )
921 val = obj->isOn( id ) ? Qt::Checked : Qt::Unchecked;
925 // NOTE! not supported currently
929 } // ... switch ( role ) ...
930 } // ... if ( obj ) ...
935 \brief Set data for the specified model index and data role.
936 \param index model index
937 \param value new data value
938 \param role data role
939 \return \c true if data is set
942 bool SUIT_TreeModel::setData( const QModelIndex& index,
943 const QVariant& value, int role )
945 if ( index.isValid() && value.isValid() ) {
946 SUIT_DataObject* obj = object( index );
948 // NOTE! only 'check state' data is supported by default
952 if ( obj->isCheckable( index.column() ) ) {
953 obj->setOn( value.toBool(), index.column() );
954 emit( dataChanged( index, index ) );
959 QString val = value.toString();
960 if ( !val.isEmpty() && obj->setName(val) ) {
961 emit( dataChanged( index, index ) );
972 return QAbstractItemModel::setData( index, value, role );
976 \brief Get data flags for specified model index.
977 \param index model index
980 Qt::ItemFlags SUIT_TreeModel::flags( const QModelIndex& index ) const
984 if (!index.isValid())
985 //return Qt::ItemIsDropEnabled; // items can be dropped into the top level of the model
988 SUIT_DataObject* obj = object(index);
991 // data object is enabled
992 if (obj->isEnabled())
993 f = f | Qt::ItemIsEnabled;
995 // data object is selectable
996 if (obj->isSelectable())
997 f = f | Qt::ItemIsSelectable;
999 // data object is checkable
1000 if (obj->isCheckable(index.column()))
1001 f = f | Qt::ItemIsUserCheckable;
1003 // data object can be renamed
1004 if (obj->renameAllowed(index.column()))
1005 f = f | Qt::ItemIsEditable;
1007 // data object can be dragged
1008 if (obj->isDraggable())
1009 f = f | Qt::ItemIsDragEnabled;
1011 // another data object(s) can be dropped on this one
1012 if (obj->isDropAccepted())
1013 f = f | Qt::ItemIsDropEnabled;
1019 Qt::DropActions SUIT_TreeModel::supportedDropActions() const
1021 return Qt::CopyAction | Qt::MoveAction;
1025 \brief Get header data (can be used in any data view).
1026 \param column column number
1027 \param orientation header orientation
1028 \param role data role
1031 QVariant SUIT_TreeModel::headerData( int column, Qt::Orientation orientation, int role ) const
1034 // NOTE! only horizontal header is supported
1035 if ( root() && orientation == Qt::Horizontal )
1041 if((myColumns[column].myHeaderFlags & Qtx::ShowText) ||
1042 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1043 d = myColumns[column].myName;
1047 case DecorationRole:
1049 if((myColumns[column].myHeaderFlags & Qtx::ShowIcon) ||
1050 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1051 d = myColumns[column].myIcon;
1055 case AppropriateRole:
1056 // appropriate flag (can column be hidden via context popup menu)
1057 d = myColumns[column].myAppropriate;
1067 \brief Create model index.
1069 \param column data column
1070 \param parent parent model index
1073 QModelIndex SUIT_TreeModel::index( int row, int column,
1074 const QModelIndex& parent ) const
1076 if( hasIndex( row, column, parent ) )
1078 TreeItem* parentItem = treeItem( parent );
1081 TreeItem* childItem = parentItem->child( row );
1083 return createIndex( row, column, childItem );
1086 return QModelIndex();
1090 \brief Get parent model index.
1091 \param index model index
1092 \return parent model index
1094 QModelIndex SUIT_TreeModel::parent( const QModelIndex& index ) const
1096 if ( !index.isValid() )
1097 return QModelIndex();
1099 TreeItem* childItem = treeItem( index );
1100 TreeItem* parentItem = childItem ? childItem->parent() : 0;
1102 if ( !parentItem || parentItem == rootItem() )
1103 return QModelIndex();
1105 return createIndex( parentItem->position(), 0, parentItem );
1109 \brief Get number of data columns.
1110 \param parent parent model index (not used)
1111 \return data columns number
1114 int SUIT_TreeModel::columnCount( const QModelIndex& /*parent*/ ) const
1116 return myColumns.size();
1120 \brief Get number of data rows (children of the specified model index).
1121 \param parent parent model index
1122 \return data rows (children) number
1125 int SUIT_TreeModel::rowCount( const QModelIndex& parent ) const
1127 // Commented by rnv in the frame of the
1128 // "20830: EDF 1357 GUI : Hide/Show Icon" imp
1129 // if ( parent.column() > 0 )
1132 TreeItem* parentItem = treeItem( parent );
1134 return parentItem ? parentItem->childCount() : 0;
1138 \brief Get data object by the specified model index.
1139 \param index model index
1140 \return data object corresponding to the model index
1142 SUIT_DataObject* SUIT_TreeModel::object( const QModelIndex& index ) const
1144 return object( treeItem( index ) );
1148 \brief Get model index by the specified data object.
1149 \param obj data object
1150 \param column data object column
1153 QModelIndex SUIT_TreeModel::index( const SUIT_DataObject* obj, int column ) const
1155 if ( obj == root() )
1156 return QModelIndex();
1158 TreeItem* item = treeItem( obj );
1160 return item ? createIndex( item->position(), column, item ) : QModelIndex();
1164 \brief Get 'auto-delete data tree' flag value.
1165 \return 'auto-delete data tree' flag value
1166 \sa setAutoDeleteTree()
1168 bool SUIT_TreeModel::autoDeleteTree() const
1170 return myAutoDeleteTree;
1174 \brief Set 'auto-delete data tree' flag value.
1176 If this flag is set to \c true, the data tree is deleted when
1177 the tree model is destroyed. Default value for this flag is \c false.
1179 \param on 'auto-delete data tree' flag value
1180 \sa autoDeleteTree()
1182 void SUIT_TreeModel::setAutoDeleteTree( const bool on )
1184 myAutoDeleteTree = on;
1188 \brief Get 'auto-update tree' flag value.
1189 \return 'auto-update tree' flag value
1190 \sa setAutoUpdate(), updateTree()
1192 bool SUIT_TreeModel::autoUpdate() const
1194 return myAutoUpdate;
1198 \brief Set 'auto-update tree' flag value.
1200 If this flag is set to \c true (by default), the model is updated
1201 automatically when data tree is changed.
1203 \param on 'auto-update tree' flag value
1204 \sa autoUpdate(), updateTree()
1206 void SUIT_TreeModel::setAutoUpdate( const bool on )
1208 if ( myAutoUpdate == on )
1211 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1212 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1213 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1214 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1217 if ( myAutoUpdate ) {
1218 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1219 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1220 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1221 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1228 \brief Get 'updateModified' flag value.
1229 \return 'updateModified' flag value
1231 bool SUIT_TreeModel::updateModified() const
1233 return myUpdateModified;
1236 \brief Set 'updateModified' flag value.
1237 \param on 'updateModified' flag value
1239 void SUIT_TreeModel::setUpdateModified(const bool on)
1241 myUpdateModified=on;
1245 \brief Check if the specified column supports custom sorting.
1246 \param column column index on which data is being sorted
1247 \return \c true if column requires custom sorting
1250 bool SUIT_TreeModel::customSorting( const int column ) const
1252 return root() ? root()->customSorting( column ) : false;
1255 void SUIT_TreeModel::forgetObject( const SUIT_DataObject* obj )
1257 removeItem( treeItem( obj ) );
1261 \brief Compares two model indexes for the sorting purposes.
1263 This method is called only for those columns for which customSorting()
1264 method returns \c true.
1266 \param left first index to compare
1267 \param right second index to compare
1268 \return result of the comparison
1271 bool SUIT_TreeModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
1273 QVariant ldata = data( left );
1274 QVariant rdata = data( right );
1275 return root() ? root()->compare( ldata, rdata, left.column() ) : false;
1279 \brief Get item delegate for the model.
1280 \return new item delegate
1282 QAbstractItemDelegate* SUIT_TreeModel::delegate() const
1284 return new SUIT_ItemDelegate( const_cast<SUIT_TreeModel*>( this ) );
1288 void SUIT_TreeModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index) {
1289 int obj_group_id = obj->groupId();
1290 const ColumnInfo& inf = myColumns[index.column()];
1293 if( inf.myIds.contains( 0 ) )
1295 if( inf.myIds.contains( obj_group_id ) )
1296 id = inf.myIds[obj_group_id];
1297 emit clicked(obj, id);
1301 \brief Update tree model.
1303 Call this method when data tree is changed outside the model.
1304 If the 'auto-update' flag is set to \c true, the model
1305 is updated automatically when the data tree is changed.
1307 \param index starting index for the updating
1310 void SUIT_TreeModel::updateTree( const QModelIndex& index )
1312 updateTree( object( index ) );
1316 void SUIT_TreeModel::updateTreeModel(SUIT_DataObject* obj,TreeItem* item)
1320 int nobjchild=obj->childCount();
1321 SUIT_DataObject* sobj=obj->childObject(kobj);
1322 TreeItem* sitem = item->child(kitem);
1324 while(kobj < nobjchild)
1329 sitem=createItemAtPos(sobj,item,kitem);
1330 updateTreeModel(sobj,sitem);
1333 sobj=obj->childObject(kobj);
1334 sitem = item->child(kitem);
1336 else if(sitem->dataObject() != sobj)
1342 sitem = item->child(kitem);
1347 sitem=createItemAtPos(sobj,item,kitem);
1348 updateTreeModel(sobj,sitem);
1351 sobj=obj->childObject(kobj);
1352 sitem = item->child(kitem);
1357 //obj and item are synchronised : go to next ones
1358 updateTreeModel(sobj,sitem);
1359 if(sobj->modified()) updateItem(sitem, true);
1363 sobj=obj->childObject(kobj);
1364 sitem = item->child(kitem);
1367 //remove remaining items
1368 for(int i = item->childCount(); i > kitem;i--)
1370 sitem = item->child(i-1);
1376 \brief Update tree model.
1378 Call this method when data tree is changed outside the model.
1379 If the 'auto-update' flag is set to \c true, the model
1380 is updated automatically when the data tree is changed.
1382 \param obj starting data object for the updating
1385 void SUIT_TreeModel::updateTree( SUIT_DataObject* obj )
1390 else if ( obj->root() != root() )
1393 if(updateModified())
1395 updateTreeModel(obj,treeItem( obj ));
1399 synchronize<ObjPtr,ItemPtr,SUIT_TreeModel::TreeSync>( obj,
1401 SUIT_TreeModel::TreeSync( this ) );
1403 emit modelUpdated();
1407 \brief Initialize tree model.
1409 void SUIT_TreeModel::initialize()
1411 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1412 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1413 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1414 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1415 if ( autoUpdate() ) {
1416 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1417 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1418 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1419 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1422 myItems.clear(); // ????? is it really necessary
1425 myRootItem = new TreeItem( 0 );
1427 registerColumn( 0, QObject::tr( "NAME_COLUMN" ), SUIT_DataObject::NameId );
1429 QString visCol = QObject::tr( "VISIBILITY_COLUMN" );
1430 registerColumn( 0, visCol, SUIT_DataObject::VisibilityId );
1432 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1433 setColumnIcon( visCol, resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ));
1434 setHeaderFlags( visCol, Qtx::ShowIcon);
1440 \brief Get root tree item.
1441 \return root tree item
1443 SUIT_TreeModel::TreeItem* SUIT_TreeModel::rootItem() const
1449 \brief Get tree item corresponding to the specified model index.
1450 \param index model index
1451 \return tree item or root item if index is invalid
1453 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const QModelIndex& index ) const
1455 return index.isValid() ? static_cast<TreeItem*>( index.internalPointer() ) : rootItem();
1459 \brief Get tree item corresponding to the specified data object.
1460 \param obj data object
1461 \return tree item or 0 if there is no tree item corresponding to \a obj
1463 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const SUIT_DataObject* obj ) const
1467 if ( obj == root() )
1469 else if ( myItems.contains( const_cast<SUIT_DataObject*>( obj ) ) )
1470 item = myItems[ const_cast<SUIT_DataObject*>( obj ) ];
1476 \brief Get data object corresponding to the specified tree item.
1477 \param item tree item
1478 \return data object or 0 if there is no data object corresponding to \a item
1480 SUIT_DataObject* SUIT_TreeModel::object( const SUIT_TreeModel::TreeItem* item ) const
1482 if ( item == rootItem() )
1485 SUIT_DataObject* obj = item ? item->dataObject() : 0;
1486 return myItems.contains( obj ) ? obj : 0;
1490 \brief Get unique object identifier
1492 Object identifier is customized via the Qtx::IdType custom data
1494 \param index model index
1495 \return object identifier or null string if it isn't specified
1496 \sa SUIT_DataObject::customData()
1498 QString SUIT_TreeModel::objectId( const QModelIndex& index ) const
1501 if ( index.isValid() ) {
1502 SUIT_DataObject* obj = object( index );
1504 int anId = obj->customData( Qtx::IdType ).toInt();
1505 objId = data( createIndex( index.row(), anId, index.internalPointer() ) ).toString();
1512 \brief Create an item corresponding to the data object.
1513 \param obj source data object
1514 \param parent parent tree item
1515 \param after tree item after which new item should be inserted
1516 \return created tree item or 0 if item could not be created
1518 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItem( SUIT_DataObject* obj,
1519 SUIT_TreeModel::TreeItem* parent,
1520 SUIT_TreeModel::TreeItem* after )
1525 SUIT_DataObject* parentObj = object( parent );
1526 QModelIndex parentIdx = index( parentObj );
1528 SUIT_DataObject* afterObj = after ? object( after ) : 0;
1529 int row = afterObj ? afterObj->position() + 1 : 0;
1531 beginInsertRows( parentIdx, row, row );
1533 myItems[ obj ] = new TreeItem( obj, parent, after );
1535 for(int pos=row;pos < parent->childCount();pos++)
1536 parent->child(pos)->setPosition(pos);
1540 obj->setModified(false);
1542 return myItems[ obj ];
1546 \brief Create an item corresponding to the data object.
1547 \param obj source data object
1548 \param parent parent tree item
1549 \param pos tree item position into which new item should be inserted
1550 \return created tree item or 0 if item could not be created
1552 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItemAtPos( SUIT_DataObject* obj,
1553 SUIT_TreeModel::TreeItem* parent,
1559 SUIT_DataObject* parentObj = object( parent );
1560 QModelIndex parentIdx = index( parentObj );
1563 SUIT_TreeModel::TreeItem* after = pos>0 ? parent->child(pos-1) : 0 ;
1565 beginInsertRows( parentIdx, row, row );
1567 SUIT_TreeModel::TreeItem* item = new TreeItem( obj, parent, after );
1568 myItems[ obj ] = item;
1570 for(int ppos=row;ppos < parent->childCount();ppos++)
1571 parent->child(ppos)->setPosition(ppos);
1575 obj->setModified(false);
1581 \brief Update tree item.
1582 \param item tree item to be updated
1583 \param emitLayoutChanged if signal about changed layout should be emitted
1585 void SUIT_TreeModel::updateItem( SUIT_TreeModel::TreeItem* item, bool emitLayoutChanged )
1590 SUIT_DataObject* obj = object( item );
1594 // update all columns corresponding to the given data object
1595 //emit layoutAboutToBeChanged(); // VSR 25/04/2011: fix crash on delete objects
1596 QModelIndex firstIdx = index( obj, 0 );
1597 QModelIndex lastIdx = index( obj, columnCount() - 1 );
1598 emit dataChanged( firstIdx, lastIdx );
1599 obj->setModified(false);
1600 if( emitLayoutChanged )
1601 emit layoutChanged();
1605 \brief Remove tree item (recursively).
1606 \param item tree item to be removed
1608 void SUIT_TreeModel::removeItem( SUIT_TreeModel::TreeItem* item )
1613 // Remove list view items from <myItems> recursively for all children.
1614 // Otherwise, "delete item" line below will destroy all item's children,
1615 // and <myItems> will contain invalid pointers
1616 while( item->childCount() )
1617 removeItem( item->child( 0 ) );
1619 SUIT_DataObject* obj = object( item );
1621 // Warning! obj can be deleted at this point!
1623 TreeItem* parent=item->parent();
1624 SUIT_DataObject* parentObj = object( parent );
1625 QModelIndex parentIdx = index( parentObj, 0 );
1626 int row = item->position();
1628 beginRemoveRows( parentIdx, row, row );
1629 myItems.remove( obj );
1631 if ( obj == root() )
1635 parent->removeChild( item );
1636 for(int pos=row;pos < parent->childCount();pos++)
1637 parent->child(pos)->setPosition(pos);
1646 \brief Called when the data object is inserted to the tree.
1647 \param object data object being inserted
1648 \param parent parent data object
1650 void SUIT_TreeModel::onInserted( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1653 updateTree( parent );
1657 \brief Called when the data object is removed from the tree.
1658 \param object data object being removed
1659 \param parent parent data object
1661 void SUIT_TreeModel::onRemoved( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1664 updateTree( parent );
1668 \brief Drag and Drop support.
1670 QStringList SUIT_TreeModel::mimeTypes() const
1673 types << "application/vnd.text.list";
1678 \brief Called when the data objects are exported(dragged) from the tree.
1679 \param indexes the list of exported objects
1681 QMimeData* SUIT_TreeModel::mimeData( const QModelIndexList& indexes ) const
1683 QMimeData* mimeData = new QMimeData();
1684 QByteArray encodedData;
1686 QDataStream stream( &encodedData, QIODevice::WriteOnly );
1688 foreach ( QModelIndex index, indexes ) {
1689 QString id = objectId( index );
1690 // we have to check only 0 column in order to avoid repeating items in the drag object
1691 // - QTreeView tries to drag indices for all visible columns
1692 if ( index.isValid() && index.column() == 0 && !id.isEmpty() )
1696 mimeData->setData( "application/vnd.text.list", encodedData );
1700 bool SUIT_TreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action,
1701 int row, int column, const QModelIndex& parent )
1703 if ( action == Qt::IgnoreAction )
1704 // do nothing with data
1707 if ( !data->hasFormat( "application/vnd.text.list" ) )
1708 // not supported data dropped
1711 if ( !parent.isValid() )
1712 // dropping into the top level of the model is not allowed
1715 // get parent object
1716 SUIT_DataObject* pobj = object( parent );
1721 // decode mime data and collect data objects being dropped
1722 QByteArray encodedData = data->data( "application/vnd.text.list" );
1723 QDataStream stream( &encodedData, QIODevice::ReadOnly );
1725 DataObjectList objects;
1727 while ( !stream.atEnd() ) {
1730 if ( !id.isEmpty() && searcher() ) {
1731 SUIT_DataObject* obj = searcher()->findObject( id );
1732 if ( obj ) objects << obj;
1737 emit dropped( objects, pobj, row, action );
1739 // return true if there's any to drop
1740 return !objects.isEmpty();
1744 \class SUIT_ProxyModel
1745 \brief Proxy model which can be used above the SUIT_TreeModel class
1746 to enable custom sorting/filtering of the data.
1748 The SUIT_TreeModel class does not support custom sorting/filtering of the data.
1749 To use these features, the SUIT_ProxyModel class can be used as top-level
1750 wrapper for the SUIT_DataObject-based data tree model.
1755 \param parent parent object
1757 SUIT_ProxyModel::SUIT_ProxyModel( QObject* parent )
1758 : QSortFilterProxyModel( parent ),
1759 mySortingEnabled( true )
1761 SUIT_TreeModel* model = new SUIT_TreeModel( this );
1762 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1763 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL(clicked( SUIT_DataObject*, int ) ) );
1764 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1765 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1766 setSourceModel( model );
1767 setDynamicSortFilter( true );
1772 \param root root data object
1773 \param parent parent object
1775 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_DataObject* root, QObject* parent )
1776 : QSortFilterProxyModel( parent ),
1777 mySortingEnabled( true )
1779 SUIT_TreeModel* model = new SUIT_TreeModel( root, this );
1780 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1781 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1782 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1783 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1784 setSourceModel( model );
1785 setDynamicSortFilter( true );
1790 \param model tree model
1791 \param parent parent object
1793 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_AbstractModel* model, QObject* parent )
1794 : QSortFilterProxyModel( parent ),
1795 mySortingEnabled( true )
1797 connect( *model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1798 connect( *model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1799 connect( *model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1800 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1801 setSourceModel( *model );
1802 setDynamicSortFilter( true );
1808 SUIT_ProxyModel::~SUIT_ProxyModel()
1813 \brief Get data tree root object.
1814 \return data tree root
1817 SUIT_DataObject* SUIT_ProxyModel::root() const
1819 return treeModel() ? treeModel()->root() : 0;
1823 \brief Set data tree root object.
1824 \param r new data tree root
1827 void SUIT_ProxyModel::setRoot( SUIT_DataObject* r )
1830 treeModel()->setRoot( r );
1834 \brief Get data object by the specified model index.
1835 \param index model index
1836 \return data object corresponding to the model index
1838 SUIT_DataObject* SUIT_ProxyModel::object( const QModelIndex& index ) const
1840 return treeModel() ? treeModel()->object( mapToSource( index ) ) : 0;
1844 \brief Get model index by the specified data object.
1845 \param obj data object
1846 \param column data object column
1849 QModelIndex SUIT_ProxyModel::index( const SUIT_DataObject* obj, int column ) const
1851 return treeModel() ? mapFromSource( treeModel()->index( obj, column ) ) : QModelIndex();
1855 \brief Get 'auto-delete data tree' flag value.
1856 \return 'auto-delete data tree' flag value
1857 \sa setAutoDeleteTree()
1859 bool SUIT_ProxyModel::autoDeleteTree() const
1861 return treeModel() ? treeModel()->autoDeleteTree() : false;
1865 \brief Set 'auto-delete data tree' flag value.
1867 If this flag is set to \c true, the data tree is deleted when
1868 the tree model is destroyed. Default value for this flag is \c false.
1870 \param on 'auto-delete data tree' flag value
1871 \sa autoDeleteTree()
1873 void SUIT_ProxyModel::setAutoDeleteTree( const bool on )
1876 treeModel()->setAutoDeleteTree( on );
1880 \brief Get 'auto-update tree' flag value.
1881 \return 'auto-update tree' flag value
1882 \sa setAutoUpdate(), updateTree()
1884 bool SUIT_ProxyModel::autoUpdate() const
1886 return treeModel() ? treeModel()->autoUpdate() : false;
1890 \brief Get 'updateModified' flag value.
1891 \return 'updateModified' flag value
1893 bool SUIT_ProxyModel::updateModified() const
1895 return treeModel() ? treeModel()->updateModified() : false;
1898 \brief Set 'updateModified' flag value.
1900 If this flag is set to \c true (default=false), the model is updated by updateTreeModel that
1901 uses the isModified flag to update only modified objects
1903 \param on 'updateModified' flag value
1905 void SUIT_ProxyModel::setUpdateModified( const bool on )
1908 treeModel()->setUpdateModified( on );
1912 \brief Set 'auto-update tree' flag value.
1914 If this flag is set to \c true (by default), the model is updated
1915 automatically when data tree is changed.
1917 \param on 'auto-update tree' flag value
1918 \sa autoUpdate(), updateTree()
1920 void SUIT_ProxyModel::setAutoUpdate( const bool on )
1923 treeModel()->setAutoUpdate( on );
1927 \brief Check if sorting is enabled.
1928 \return \c true if sorting is enabled
1929 \sa setSortingEnabled()
1931 bool SUIT_ProxyModel::isSortingEnabled() const
1933 return mySortingEnabled;
1936 SUIT_DataSearcher* SUIT_ProxyModel::searcher() const
1938 return treeModel() ? treeModel()->searcher() : 0;
1941 void SUIT_ProxyModel::setSearcher( SUIT_DataSearcher* s )
1943 if ( treeModel() ) treeModel()->setSearcher( s );
1947 \brief Get item delegate for the model.
1948 \return new item delegate
1950 QAbstractItemDelegate* SUIT_ProxyModel::delegate() const
1952 return treeModel() ? treeModel()->delegate() : 0;
1956 \brief Update tree model.
1958 Call this method when data tree is changed outside the model.
1959 If the 'auto-update' flag is set to \c true, the model
1960 is updated automatically when the data tree is changed.
1962 \param index starting index for the updating
1965 void SUIT_ProxyModel::updateTree( const QModelIndex& index )
1968 treeModel()->updateTree( mapToSource( index ) );
1972 \brief Update tree model.
1974 Call this method when data tree is changed outside the model.
1975 If the 'auto-update' flag is set to \c true, the model
1976 is updated automatically when the data tree is changed.
1978 \param obj starting data object for the updating
1981 void SUIT_ProxyModel::updateTree( SUIT_DataObject* obj )
1984 treeModel()->updateTree( obj );
1987 void SUIT_ProxyModel::forgetObject( const SUIT_DataObject* obj )
1990 treeModel()->forgetObject( obj );
1994 \brief Compares two model indexes for the sorting purposes.
1995 \param left first index to compare
1996 \param right second index to compare
1997 \return result of the comparison
1999 bool SUIT_ProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
2001 if ( !isSortingEnabled() && left.isValid() && right.isValid() ) {
2002 return left.row() < right.row();
2004 if ( treeModel() && treeModel()->customSorting( left.column() ) ) {
2005 return treeModel()->lessThan( left, right );
2007 return QSortFilterProxyModel::lessThan( left, right );
2011 \brief Check if the specified column supports custom sorting.
2012 \param column column index on which data is being sorted
2013 \return \c true if column requires custom sorting
2016 bool SUIT_ProxyModel::customSorting( const int column ) const
2018 return treeModel() ? treeModel()->customSorting( column ) : false;
2022 \brief Enable/disable sorting.
2023 \param enabled new flag state
2024 \sa isSortingEnabled()
2026 void SUIT_ProxyModel::setSortingEnabled( bool enabled )
2028 mySortingEnabled = enabled;
2033 \brief Get tree model.
2036 SUIT_AbstractModel* SUIT_ProxyModel::treeModel() const
2038 return dynamic_cast<SUIT_AbstractModel*>( sourceModel() );
2043 \param sourceRow row index of the source data model
2044 \param sourceParent parent model index of the source data model
2045 \return \c true if the specified row should be filtered out (i.e. not displayed) or \c false otherwise
2047 bool SUIT_ProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
2049 SUIT_DataObject* o = treeModel()->object( sourceModel()->index( sourceRow, 0, sourceParent ) );
2050 SUIT_DataObject* p = o ? o->parent() : 0;
2051 return ( !p || p->expandable() ) && o && o->isVisible();
2055 \brief Register new column in the model
2056 \param group_id - unique data object identificator allowing the classification of objects
2057 \param name - translated column name
2058 \param custom_id - custom column id that should be passed into method SUIT_DataObject::data()
2060 void SUIT_ProxyModel::registerColumn( const int group_id, const QString& name, const int custom_id )
2063 treeModel()->registerColumn( group_id, name, custom_id );
2067 \brief Remove column from the model
2069 Please take into account that column is removed only for given group_id, it means
2070 that information of data objects with such group_id won't be shown.
2071 If there is not any registered group_id for this column after removing, the column will be hidden
2072 otherwise it continue to be shown
2074 \param group_id - unique data object identificator allowing the classification of objects
2075 \param name - translated column name
2077 void SUIT_ProxyModel::unregisterColumn( const int group_id, const QString& name )
2080 treeModel()->unregisterColumn( group_id, name );
2084 \brief Change column icon.
2086 \param name - column name
2087 \param icon - new icon of the specified column
2089 void SUIT_ProxyModel::setColumnIcon( const QString& name, const QPixmap& icon )
2092 treeModel()->setColumnIcon( name, icon );
2096 \brief Get column icon.
2098 \param name - column name
2099 \return icon of the specified column
2101 QPixmap SUIT_ProxyModel::columnIcon( const QString& name ) const
2103 return treeModel() ? treeModel()->columnIcon( name ) : QPixmap();
2107 \brief Change appropriate status
2109 Appropriate status determines if the column should appear in the tree view header popup menu
2110 (to show/hide the column).
2112 If appropriate status is not specified yet, the \c Shown value is taken,
2113 it means that column should be always visible.
2115 \param name - column name
2116 \param appr - new appropriate status
2118 void SUIT_ProxyModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
2121 treeModel()->setAppropriate( name, appr );
2125 \brief Check if the column should appear in the tree view header popup menu
2126 (to show/hide the column).
2128 Default implementation (if appropriate status is not specified yet)
2129 returns \c Shown, it means that column should be always visible.
2131 \param name - column name
2132 \return appropriate status
2134 Qtx::Appropriate SUIT_ProxyModel::appropriate( const QString& name ) const
2136 return treeModel() ? treeModel()->appropriate( name ) : Qtx::Shown;
2140 \brief Set header flags.
2142 These flags allow show in the header of the column text (name of the column),
2143 icon or both text and icon.
2145 \param name - column name
2146 \param flags - header flags
2149 void SUIT_ProxyModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
2152 treeModel()->setHeaderFlags(name, flags);
2156 \brief Get the header flags.
2158 These flags allow show in the header of the column text (name of the column),
2159 icon or both text and icon.
2161 \param name - column name
2162 \return header flags
2164 Qtx::HeaderViewFlags SUIT_ProxyModel::headerFlags( const QString& name ) const
2166 return treeModel() ? treeModel()->headerFlags( name ) : Qtx::ShowAll;
2170 \brief Set visibility state of the object.
2172 \param id - column name
2173 \param state - visible state
2175 void SUIT_ProxyModel::setVisibilityState(const QString& id, Qtx::VisibilityState state)
2178 treeModel()->setVisibilityState(id,state);
2182 \brief Set visibility state for all objects.
2184 \param id - column name
2185 \param state - visible state
2187 void SUIT_ProxyModel::setVisibilityStateForAll(Qtx::VisibilityState state)
2190 treeModel()->setVisibilityStateForAll(state);
2194 \brief Get visibility state of the object.
2196 \param id - column name
2197 \return visible state
2199 Qtx::VisibilityState SUIT_ProxyModel::visibilityState(const QString& id) const
2201 return treeModel() ? treeModel()->visibilityState(id) : Qtx::UnpresentableState;
2204 void SUIT_ProxyModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index)
2207 treeModel()->emitClicked(obj,index);
2211 \class SUIT_ItemDelegate
2212 \brief An SUIT_DataObject-based item delegate class.
2214 This class can be used to render the SUIT_DataObject-based item
2215 in the widgets like QTreeView and others.
2216 Refer to the Qt 4 documentation, model/view architecture
2217 section for more details).
2222 \param parent parent object
2224 SUIT_ItemDelegate::SUIT_ItemDelegate( QObject* parent )
2225 : QItemDelegate( parent )
2230 \brief Render the item in the widget.
2232 Customizes the item colors for the specific roles.
2234 \param painter painter
2235 \param option painting option
2236 \param index model index being rendered
2238 void SUIT_ItemDelegate::paint( QPainter* painter,
2239 const QStyleOptionViewItem& option,
2240 const QModelIndex& index ) const
2242 QStyleOptionViewItem opt = option;
2243 if ( index.isValid() ) {
2244 // Note: we check into account only custom roles; other roles are process
2245 // correctly by the QItemDelegate class
2246 QVariant val = index.data( SUIT_TreeModel::BaseColorRole );
2247 if ( val.isValid() && val.value<QColor>().isValid() ) {
2248 QColor aBase = val.value<QColor>();
2249 aBase.setAlpha( 0 );
2250 opt.palette.setBrush( QPalette::Base, val.value<QColor>() );
2252 val = index.data( SUIT_TreeModel::TextColorRole );
2253 if ( val.isValid() && val.value<QColor>().isValid() )
2254 opt.palette.setBrush( QPalette::Text, val.value<QColor>() );
2255 val = index.data( SUIT_TreeModel::HighlightRole );
2256 if ( val.isValid() && val.value<QColor>().isValid() )
2257 opt.palette.setBrush( QPalette::Highlight, val.value<QColor>() );
2258 val = index.data( SUIT_TreeModel::HighlightedTextRole );
2259 if ( val.isValid() && val.value<QColor>().isValid() )
2260 opt.palette.setBrush( QPalette::HighlightedText, val.value<QColor>() );
2262 QItemDelegate::paint( painter, opt, index );
2265 QSize SUIT_ItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
2267 QSize size = QItemDelegate::sizeHint ( option, index );
2268 #if QT_VERSION >= 0x040500
2269 size.setHeight( size.height() + 1 );