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)
1330 sitem=createItemAtPos(sobj,item,0);
1332 sitem=createItemAtPos(sobj,item,kitem);
1333 updateTreeModel(sobj,sitem);
1336 sobj=obj->childObject(kobj);
1337 sitem = item->child(kitem);
1339 else if(sitem->dataObject() != sobj)
1345 sitem = item->child(kitem);
1350 createItemAtPos(sobj,item,kitem);
1353 sobj=obj->childObject(kobj);
1354 sitem = item->child(kitem);
1359 //obj and item are synchronised : go to next ones
1360 updateTreeModel(sobj,sitem);
1361 if(sobj->modified()) updateItem(sitem, true);
1362 if( sobj ) sobj->update();
1365 sobj=obj->childObject(kobj);
1366 sitem = item->child(kitem);
1369 //remove remaining items
1370 for(int i = item->childCount(); i > kitem;i--)
1372 sitem = item->child(i-1);
1378 \brief Update tree model.
1380 Call this method when data tree is changed outside the model.
1381 If the 'auto-update' flag is set to \c true, the model
1382 is updated automatically when the data tree is changed.
1384 \param obj starting data object for the updating
1387 void SUIT_TreeModel::updateTree( SUIT_DataObject* obj )
1392 else if ( obj->root() != root() )
1395 if(updateModified())
1397 updateTreeModel(obj,treeItem( obj ));
1401 synchronize<ObjPtr,ItemPtr,SUIT_TreeModel::TreeSync>( obj,
1403 SUIT_TreeModel::TreeSync( this ) );
1405 emit modelUpdated();
1409 \brief Initialize tree model.
1411 void SUIT_TreeModel::initialize()
1413 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1414 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1415 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1416 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1417 if ( autoUpdate() ) {
1418 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1419 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1420 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1421 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1424 myItems.clear(); // ????? is it really necessary
1427 myRootItem = new TreeItem( 0 );
1429 registerColumn( 0, QObject::tr( "NAME_COLUMN" ), SUIT_DataObject::NameId );
1431 QString visCol = QObject::tr( "VISIBILITY_COLUMN" );
1432 registerColumn( 0, visCol, SUIT_DataObject::VisibilityId );
1434 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1435 setColumnIcon( visCol, resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ));
1436 setHeaderFlags( visCol, Qtx::ShowIcon);
1442 \brief Get root tree item.
1443 \return root tree item
1445 SUIT_TreeModel::TreeItem* SUIT_TreeModel::rootItem() const
1451 \brief Get tree item corresponding to the specified model index.
1452 \param index model index
1453 \return tree item or root item if index is invalid
1455 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const QModelIndex& index ) const
1457 return index.isValid() ? static_cast<TreeItem*>( index.internalPointer() ) : rootItem();
1461 \brief Get tree item corresponding to the specified data object.
1462 \param obj data object
1463 \return tree item or 0 if there is no tree item corresponding to \a obj
1465 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const SUIT_DataObject* obj ) const
1469 if ( obj == root() )
1471 else if ( myItems.contains( const_cast<SUIT_DataObject*>( obj ) ) )
1472 item = myItems[ const_cast<SUIT_DataObject*>( obj ) ];
1478 \brief Get data object corresponding to the specified tree item.
1479 \param item tree item
1480 \return data object or 0 if there is no data object corresponding to \a item
1482 SUIT_DataObject* SUIT_TreeModel::object( const SUIT_TreeModel::TreeItem* item ) const
1484 if ( item == rootItem() )
1487 SUIT_DataObject* obj = item ? item->dataObject() : 0;
1488 return myItems.contains( obj ) ? obj : 0;
1492 \brief Get unique object identifier
1494 Object identifier is customized via the Qtx::IdType custom data
1496 \param index model index
1497 \return object identifier or null string if it isn't specified
1498 \sa SUIT_DataObject::customData()
1500 QString SUIT_TreeModel::objectId( const QModelIndex& index ) const
1503 if ( index.isValid() ) {
1504 SUIT_DataObject* obj = object( index );
1506 int anId = obj->customData( Qtx::IdType ).toInt();
1507 objId = data( createIndex( index.row(), anId, index.internalPointer() ) ).toString();
1514 \brief Create an item corresponding to the data object.
1515 \param obj source data object
1516 \param parent parent tree item
1517 \param after tree item after which new item should be inserted
1518 \return created tree item or 0 if item could not be created
1520 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItem( SUIT_DataObject* obj,
1521 SUIT_TreeModel::TreeItem* parent,
1522 SUIT_TreeModel::TreeItem* after )
1527 SUIT_DataObject* parentObj = object( parent );
1528 QModelIndex parentIdx = index( parentObj );
1530 SUIT_DataObject* afterObj = after ? object( after ) : 0;
1531 int row = afterObj ? afterObj->position() + 1 : 0;
1533 beginInsertRows( parentIdx, row, row );
1535 myItems[ obj ] = new TreeItem( obj, parent, after );
1537 for(int pos=row;pos < parent->childCount();pos++)
1538 parent->child(pos)->setPosition(pos);
1542 obj->setModified(false);
1544 return myItems[ obj ];
1548 \brief Create an item corresponding to the data object.
1549 \param obj source data object
1550 \param parent parent tree item
1551 \param pos tree item position into which new item should be inserted
1552 \return created tree item or 0 if item could not be created
1554 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItemAtPos( SUIT_DataObject* obj,
1555 SUIT_TreeModel::TreeItem* parent,
1561 SUIT_DataObject* parentObj = object( parent );
1562 QModelIndex parentIdx = index( parentObj );
1565 SUIT_TreeModel::TreeItem* after = pos>0 ? parent->child(pos-1) : 0 ;
1567 beginInsertRows( parentIdx, row, row );
1569 SUIT_TreeModel::TreeItem* item = new TreeItem( obj, parent, after );
1570 myItems[ obj ] = item;
1572 for(int pos=row;pos < parent->childCount();pos++)
1573 parent->child(pos)->setPosition(pos);
1577 obj->setModified(false);
1583 \brief Update tree item.
1584 \param item tree item to be updated
1585 \param emitLayoutChanged if signal about changed layout should be emitted
1587 void SUIT_TreeModel::updateItem( SUIT_TreeModel::TreeItem* item, bool emitLayoutChanged )
1592 SUIT_DataObject* obj = object( item );
1596 // update all columns corresponding to the given data object
1597 //emit layoutAboutToBeChanged(); // VSR 25/04/2011: fix crash on delete objects
1598 QModelIndex firstIdx = index( obj, 0 );
1599 QModelIndex lastIdx = index( obj, columnCount() - 1 );
1600 emit dataChanged( firstIdx, lastIdx );
1601 obj->setModified(false);
1602 if( emitLayoutChanged )
1603 emit layoutChanged();
1607 \brief Remove tree item (recursively).
1608 \param item tree item to be removed
1610 void SUIT_TreeModel::removeItem( SUIT_TreeModel::TreeItem* item )
1615 // Remove list view items from <myItems> recursively for all children.
1616 // Otherwise, "delete item" line below will destroy all item's children,
1617 // and <myItems> will contain invalid pointers
1618 while( item->childCount() )
1619 removeItem( item->child( 0 ) );
1621 SUIT_DataObject* obj = object( item );
1623 // Warning! obj can be deleted at this point!
1625 TreeItem* parent=item->parent();
1626 SUIT_DataObject* parentObj = object( parent );
1627 QModelIndex parentIdx = index( parentObj, 0 );
1628 int row = item->position();
1630 beginRemoveRows( parentIdx, row, row );
1631 myItems.remove( obj );
1633 if ( obj == root() )
1637 parent->removeChild( item );
1638 for(int pos=row;pos < parent->childCount();pos++)
1639 parent->child(pos)->setPosition(pos);
1648 \brief Called when the data object is inserted to the tree.
1649 \param object data object being inserted
1650 \param parent parent data object
1652 void SUIT_TreeModel::onInserted( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1655 updateTree( parent );
1659 \brief Called when the data object is removed from the tree.
1660 \param object data object being removed
1661 \param parent parent data object
1663 void SUIT_TreeModel::onRemoved( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1666 updateTree( parent );
1670 \brief Drag and Drop support.
1672 QStringList SUIT_TreeModel::mimeTypes() const
1675 types << "application/vnd.text.list";
1680 \brief Called when the data objects are exported(dragged) from the tree.
1681 \param indexes the list of exported objects
1683 QMimeData* SUIT_TreeModel::mimeData( const QModelIndexList& indexes ) const
1685 QMimeData* mimeData = new QMimeData();
1686 QByteArray encodedData;
1688 QDataStream stream( &encodedData, QIODevice::WriteOnly );
1690 foreach ( QModelIndex index, indexes ) {
1691 QString id = objectId( index );
1692 // we have to check only 0 column in order to avoid repeating items in the drag object
1693 // - QTreeView tries to drag indices for all visible columns
1694 if ( index.isValid() && index.column() == 0 && !id.isEmpty() )
1698 mimeData->setData( "application/vnd.text.list", encodedData );
1702 bool SUIT_TreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action,
1703 int row, int column, const QModelIndex& parent )
1705 if ( action == Qt::IgnoreAction )
1706 // do nothing with data
1709 if ( !data->hasFormat( "application/vnd.text.list" ) )
1710 // not supported data dropped
1713 if ( !parent.isValid() )
1714 // dropping into the top level of the model is not allowed
1717 // get parent object
1718 SUIT_DataObject* pobj = object( parent );
1723 // decode mime data and collect data objects being dropped
1724 QByteArray encodedData = data->data( "application/vnd.text.list" );
1725 QDataStream stream( &encodedData, QIODevice::ReadOnly );
1727 DataObjectList objects;
1729 while ( !stream.atEnd() ) {
1732 if ( !id.isEmpty() && searcher() ) {
1733 SUIT_DataObject* obj = searcher()->findObject( id );
1734 if ( obj ) objects << obj;
1739 emit dropped( objects, pobj, row, action );
1741 // return true if there's any to drop
1742 return !objects.isEmpty();
1746 \class SUIT_ProxyModel
1747 \brief Proxy model which can be used above the SUIT_TreeModel class
1748 to enable custom sorting/filtering of the data.
1750 The SUIT_TreeModel class does not support custom sorting/filtering of the data.
1751 To use these features, the SUIT_ProxyModel class can be used as top-level
1752 wrapper for the SUIT_DataObject-based data tree model.
1757 \param parent parent object
1759 SUIT_ProxyModel::SUIT_ProxyModel( QObject* parent )
1760 : QSortFilterProxyModel( parent ),
1761 mySortingEnabled( true )
1763 SUIT_TreeModel* model = new SUIT_TreeModel( this );
1764 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1765 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL(clicked( SUIT_DataObject*, int ) ) );
1766 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1767 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1768 setSourceModel( model );
1769 setDynamicSortFilter( true );
1774 \param root root data object
1775 \param parent parent object
1777 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_DataObject* root, QObject* parent )
1778 : QSortFilterProxyModel( parent ),
1779 mySortingEnabled( true )
1781 SUIT_TreeModel* model = new SUIT_TreeModel( root, this );
1782 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1783 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1784 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1785 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1786 setSourceModel( model );
1787 setDynamicSortFilter( true );
1792 \param model tree model
1793 \param parent parent object
1795 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_AbstractModel* model, QObject* parent )
1796 : QSortFilterProxyModel( parent ),
1797 mySortingEnabled( true )
1799 connect( *model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1800 connect( *model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1801 connect( *model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1802 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1803 setSourceModel( *model );
1804 setDynamicSortFilter( true );
1810 SUIT_ProxyModel::~SUIT_ProxyModel()
1815 \brief Get data tree root object.
1816 \return data tree root
1819 SUIT_DataObject* SUIT_ProxyModel::root() const
1821 return treeModel() ? treeModel()->root() : 0;
1825 \brief Set data tree root object.
1826 \param r new data tree root
1829 void SUIT_ProxyModel::setRoot( SUIT_DataObject* r )
1832 treeModel()->setRoot( r );
1836 \brief Get data object by the specified model index.
1837 \param index model index
1838 \return data object corresponding to the model index
1840 SUIT_DataObject* SUIT_ProxyModel::object( const QModelIndex& index ) const
1842 return treeModel() ? treeModel()->object( mapToSource( index ) ) : 0;
1846 \brief Get model index by the specified data object.
1847 \param obj data object
1848 \param column data object column
1851 QModelIndex SUIT_ProxyModel::index( const SUIT_DataObject* obj, int column ) const
1853 return treeModel() ? mapFromSource( treeModel()->index( obj, column ) ) : QModelIndex();
1857 \brief Get 'auto-delete data tree' flag value.
1858 \return 'auto-delete data tree' flag value
1859 \sa setAutoDeleteTree()
1861 bool SUIT_ProxyModel::autoDeleteTree() const
1863 return treeModel() ? treeModel()->autoDeleteTree() : false;
1867 \brief Set 'auto-delete data tree' flag value.
1869 If this flag is set to \c true, the data tree is deleted when
1870 the tree model is destroyed. Default value for this flag is \c false.
1872 \param on 'auto-delete data tree' flag value
1873 \sa autoDeleteTree()
1875 void SUIT_ProxyModel::setAutoDeleteTree( const bool on )
1878 treeModel()->setAutoDeleteTree( on );
1882 \brief Get 'auto-update tree' flag value.
1883 \return 'auto-update tree' flag value
1884 \sa setAutoUpdate(), updateTree()
1886 bool SUIT_ProxyModel::autoUpdate() const
1888 return treeModel() ? treeModel()->autoUpdate() : false;
1892 \brief Get 'updateModified' flag value.
1893 \return 'updateModified' flag value
1895 bool SUIT_ProxyModel::updateModified() const
1897 return treeModel() ? treeModel()->updateModified() : false;
1900 \brief Set 'updateModified' flag value.
1902 If this flag is set to \c true (default=false), the model is updated by updateTreeModel that
1903 uses the isModified flag to update only modified objects
1905 \param on 'updateModified' flag value
1907 void SUIT_ProxyModel::setUpdateModified( const bool on )
1910 treeModel()->setUpdateModified( on );
1914 \brief Set 'auto-update tree' flag value.
1916 If this flag is set to \c true (by default), the model is updated
1917 automatically when data tree is changed.
1919 \param on 'auto-update tree' flag value
1920 \sa autoUpdate(), updateTree()
1922 void SUIT_ProxyModel::setAutoUpdate( const bool on )
1925 treeModel()->setAutoUpdate( on );
1929 \brief Check if sorting is enabled.
1930 \return \c true if sorting is enabled
1931 \sa setSortingEnabled()
1933 bool SUIT_ProxyModel::isSortingEnabled() const
1935 return mySortingEnabled;
1938 SUIT_DataSearcher* SUIT_ProxyModel::searcher() const
1940 return treeModel() ? treeModel()->searcher() : 0;
1943 void SUIT_ProxyModel::setSearcher( SUIT_DataSearcher* s )
1945 if ( treeModel() ) treeModel()->setSearcher( s );
1949 \brief Get item delegate for the model.
1950 \return new item delegate
1952 QAbstractItemDelegate* SUIT_ProxyModel::delegate() const
1954 return treeModel() ? treeModel()->delegate() : 0;
1958 \brief Update tree model.
1960 Call this method when data tree is changed outside the model.
1961 If the 'auto-update' flag is set to \c true, the model
1962 is updated automatically when the data tree is changed.
1964 \param index starting index for the updating
1967 void SUIT_ProxyModel::updateTree( const QModelIndex& index )
1970 treeModel()->updateTree( mapToSource( index ) );
1974 \brief Update tree model.
1976 Call this method when data tree is changed outside the model.
1977 If the 'auto-update' flag is set to \c true, the model
1978 is updated automatically when the data tree is changed.
1980 \param obj starting data object for the updating
1983 void SUIT_ProxyModel::updateTree( SUIT_DataObject* obj )
1986 treeModel()->updateTree( obj );
1989 void SUIT_ProxyModel::forgetObject( const SUIT_DataObject* obj )
1992 treeModel()->forgetObject( obj );
1996 \brief Compares two model indexes for the sorting purposes.
1997 \param left first index to compare
1998 \param right second index to compare
1999 \return result of the comparison
2001 bool SUIT_ProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
2003 if ( !isSortingEnabled() && left.isValid() && right.isValid() ) {
2004 return left.row() < right.row();
2006 if ( treeModel() && treeModel()->customSorting( left.column() ) ) {
2007 return treeModel()->lessThan( left, right );
2009 return QSortFilterProxyModel::lessThan( left, right );
2013 \brief Check if the specified column supports custom sorting.
2014 \param column column index on which data is being sorted
2015 \return \c true if column requires custom sorting
2018 bool SUIT_ProxyModel::customSorting( const int column ) const
2020 return treeModel() ? treeModel()->customSorting( column ) : false;
2024 \brief Enable/disable sorting.
2025 \param enabled new flag state
2026 \sa isSortingEnabled()
2028 void SUIT_ProxyModel::setSortingEnabled( bool enabled )
2030 mySortingEnabled = enabled;
2035 \brief Get tree model.
2038 SUIT_AbstractModel* SUIT_ProxyModel::treeModel() const
2040 return dynamic_cast<SUIT_AbstractModel*>( sourceModel() );
2045 \param sourceRow row index of the source data model
2046 \param sourceParent parent model index of the source data model
2047 \return \c true if the specified row should be filtered out (i.e. not displayed) or \c false otherwise
2049 bool SUIT_ProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
2051 SUIT_DataObject* o = treeModel()->object( sourceModel()->index( sourceRow, 0, sourceParent ) );
2052 SUIT_DataObject* p = o ? o->parent() : 0;
2053 return ( !p || p->expandable() ) && o && o->isVisible();
2057 \brief Register new column in the model
2058 \param group_id - unique data object identificator allowing the classification of objects
2059 \param name - translated column name
2060 \param custom_id - custom column id that should be passed into method SUIT_DataObject::data()
2062 void SUIT_ProxyModel::registerColumn( const int group_id, const QString& name, const int custom_id )
2065 treeModel()->registerColumn( group_id, name, custom_id );
2069 \brief Remove column from the model
2071 Please take into account that column is removed only for given group_id, it means
2072 that information of data objects with such group_id won't be shown.
2073 If there is not any registered group_id for this column after removing, the column will be hidden
2074 otherwise it continue to be shown
2076 \param group_id - unique data object identificator allowing the classification of objects
2077 \param name - translated column name
2079 void SUIT_ProxyModel::unregisterColumn( const int group_id, const QString& name )
2082 treeModel()->unregisterColumn( group_id, name );
2086 \brief Change column icon.
2088 \param name - column name
2089 \param icon - new icon of the specified column
2091 void SUIT_ProxyModel::setColumnIcon( const QString& name, const QPixmap& icon )
2094 treeModel()->setColumnIcon( name, icon );
2098 \brief Get column icon.
2100 \param name - column name
2101 \return icon of the specified column
2103 QPixmap SUIT_ProxyModel::columnIcon( const QString& name ) const
2105 return treeModel() ? treeModel()->columnIcon( name ) : QPixmap();
2109 \brief Change appropriate status
2111 Appropriate status determines if the column should appear in the tree view header popup menu
2112 (to show/hide the column).
2114 If appropriate status is not specified yet, the \c Shown value is taken,
2115 it means that column should be always visible.
2117 \param name - column name
2118 \param appr - new appropriate status
2120 void SUIT_ProxyModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
2123 treeModel()->setAppropriate( name, appr );
2127 \brief Check if the column should appear in the tree view header popup menu
2128 (to show/hide the column).
2130 Default implementation (if appropriate status is not specified yet)
2131 returns \c Shown, it means that column should be always visible.
2133 \param name - column name
2134 \return appropriate status
2136 Qtx::Appropriate SUIT_ProxyModel::appropriate( const QString& name ) const
2138 return treeModel() ? treeModel()->appropriate( name ) : Qtx::Shown;
2142 \brief Set header flags.
2144 These flags allow show in the header of the column text (name of the column),
2145 icon or both text and icon.
2147 \param name - column name
2148 \param flags - header flags
2151 void SUIT_ProxyModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
2154 treeModel()->setHeaderFlags(name, flags);
2158 \brief Get the header flags.
2160 These flags allow show in the header of the column text (name of the column),
2161 icon or both text and icon.
2163 \param name - column name
2164 \return header flags
2166 Qtx::HeaderViewFlags SUIT_ProxyModel::headerFlags( const QString& name ) const
2168 return treeModel() ? treeModel()->headerFlags( name ) : Qtx::ShowAll;
2172 \brief Set visibility state of the object.
2174 \param id - column name
2175 \param state - visible state
2177 void SUIT_ProxyModel::setVisibilityState(const QString& id, Qtx::VisibilityState state)
2180 treeModel()->setVisibilityState(id,state);
2184 \brief Set visibility state for all objects.
2186 \param id - column name
2187 \param state - visible state
2189 void SUIT_ProxyModel::setVisibilityStateForAll(Qtx::VisibilityState state)
2192 treeModel()->setVisibilityStateForAll(state);
2196 \brief Get visibility state of the object.
2198 \param id - column name
2199 \return visible state
2201 Qtx::VisibilityState SUIT_ProxyModel::visibilityState(const QString& id) const
2203 return treeModel() ? treeModel()->visibilityState(id) : Qtx::UnpresentableState;
2206 void SUIT_ProxyModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index)
2209 treeModel()->emitClicked(obj,index);
2213 \class SUIT_ItemDelegate
2214 \brief An SUIT_DataObject-based item delegate class.
2216 This class can be used to render the SUIT_DataObject-based item
2217 in the widgets like QTreeView and others.
2218 Refer to the Qt 4 documentation, model/view architecture
2219 section for more details).
2224 \param parent parent object
2226 SUIT_ItemDelegate::SUIT_ItemDelegate( QObject* parent )
2227 : QItemDelegate( parent )
2232 \brief Render the item in the widget.
2234 Customizes the item colors for the specific roles.
2236 \param painter painter
2237 \param option painting option
2238 \param index model index being rendered
2240 void SUIT_ItemDelegate::paint( QPainter* painter,
2241 const QStyleOptionViewItem& option,
2242 const QModelIndex& index ) const
2244 QStyleOptionViewItem opt = option;
2245 if ( index.isValid() ) {
2246 // Note: we check into account only custom roles; other roles are process
2247 // correctly by the QItemDelegate class
2248 QVariant val = index.data( SUIT_TreeModel::BaseColorRole );
2249 if ( val.isValid() && val.value<QColor>().isValid() ) {
2250 QColor aBase = val.value<QColor>();
2251 aBase.setAlpha( 0 );
2252 opt.palette.setBrush( QPalette::Base, val.value<QColor>() );
2254 val = index.data( SUIT_TreeModel::TextColorRole );
2255 if ( val.isValid() && val.value<QColor>().isValid() )
2256 opt.palette.setBrush( QPalette::Text, val.value<QColor>() );
2257 val = index.data( SUIT_TreeModel::HighlightRole );
2258 if ( val.isValid() && val.value<QColor>().isValid() )
2259 opt.palette.setBrush( QPalette::Highlight, val.value<QColor>() );
2260 val = index.data( SUIT_TreeModel::HighlightedTextRole );
2261 if ( val.isValid() && val.value<QColor>().isValid() )
2262 opt.palette.setBrush( QPalette::HighlightedText, val.value<QColor>() );
2264 QItemDelegate::paint( painter, opt, index );
2267 QSize SUIT_ItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
2269 QSize size = QItemDelegate::sizeHint ( option, index );
2270 #if QT_VERSION >= 0x040500
2271 size.setHeight( size.height() + 1 );