1 // Copyright (C) 2007-2015 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, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: SUIT_TreeModel.cxx
21 // Author: Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
23 #include "SUIT_Session.h"
24 #include "SUIT_TreeModel.h"
25 #include "SUIT_TreeSync.h"
26 #include "SUIT_DataObject.h"
27 #include "SUIT_ResourceMgr.h"
29 #include <QApplication>
33 SUIT_AbstractModel::SUIT_AbstractModel() : mySearcher( 0 )
37 SUIT_AbstractModel::operator const QAbstractItemModel*() const
39 return dynamic_cast<const QAbstractItemModel*>( this );
42 SUIT_AbstractModel::operator QAbstractItemModel*()
44 return dynamic_cast<QAbstractItemModel*>( this );
47 SUIT_AbstractModel::operator const QObject*() const
49 return dynamic_cast<const QObject*>( this );
52 SUIT_DataSearcher* SUIT_AbstractModel::searcher() const
57 void SUIT_AbstractModel::setSearcher( SUIT_DataSearcher* s )
64 \class SUIT_TreeModel::TreeItem
65 \brief Internal class used for tree view synchronizaton with data object tree.
69 class SUIT_TreeModel::TreeItem
72 TreeItem( SUIT_DataObject* obj, TreeItem* parent = 0, TreeItem* after = 0 );
75 void insertChild( TreeItem* child, TreeItem* after = 0 );
76 void removeChild( TreeItem* child );
77 SUIT_DataObject* dataObject() const;
78 TreeItem* parent() const;
80 void setPosition(int position) {_position=position;};
81 int childCount() const;
82 TreeItem* child( const int i );
83 QList<TreeItem*> children() const;
84 TreeItem* nextSibling() const;
85 TreeItem* prevSibling() const;
89 QList<TreeItem*> myChildren;
90 SUIT_DataObject* myObj;
97 \param obj data object
98 \param parent parent item
99 \param after tree item after each this one should be inserted
101 SUIT_TreeModel::TreeItem::TreeItem( SUIT_DataObject* obj,
102 SUIT_TreeModel::TreeItem* parent,
103 SUIT_TreeModel::TreeItem* after )
104 : myParent( parent ),
108 // Add <this> to the parent's children list
110 myParent->insertChild( this, after );
114 \brief Destructor. Deletes all child items recursively.
117 SUIT_TreeModel::TreeItem::~TreeItem()
119 // Ensure that all children are deleted;
120 // each child removes itself from the children list
121 while( myChildren.count() )
122 delete myChildren.at( 0 );
124 // Remove this item from the parent's children list
126 myParent->removeChild( this );
130 \brief Insert child item.
132 \param child child item being inserted
133 \param after tree item after each \a child should be inserted
135 void SUIT_TreeModel::TreeItem::insertChild( SUIT_TreeModel::TreeItem* child,
136 SUIT_TreeModel::TreeItem* after )
141 int index = after ? after->position() + 1 : 0;
142 myChildren.insert( index, child );
146 \brief Remove child item.
148 \param child child item being removed
150 void SUIT_TreeModel::TreeItem::removeChild( SUIT_TreeModel::TreeItem* child )
154 myChildren.removeAll( child );
158 \brief Get data object.
160 \return data object this item is associated to
162 SUIT_DataObject* SUIT_TreeModel::TreeItem::dataObject() const
168 \brief Get parent item.
172 SUIT_TreeModel::TreeItem* SUIT_TreeModel::TreeItem::parent() const
178 \brief Get position of this item in its parent's children list.
180 \return item position
182 int SUIT_TreeModel::TreeItem::position() const
188 \brief Get number of child items.
190 \return number of children
192 int SUIT_TreeModel::TreeItem::childCount() const
194 return myChildren.count();
198 \brief Get child item by specified index.
200 \param i child item index
201 \return child item or 0 if \a i is out of range
203 SUIT_TreeModel::TreeItem* SUIT_TreeModel::TreeItem::child( const int i )
205 return i >= 0 && i < myChildren.count() ? myChildren.at( i ) : 0;
209 \brief Get all child items.
211 \return list of child items
213 QList<SUIT_TreeModel::TreeItem*> SUIT_TreeModel::TreeItem::children() const
219 \brief Get next sibling item.
221 \return next sibling item or 0 if there are no any
223 SUIT_TreeModel::TreeItem* SUIT_TreeModel::TreeItem::nextSibling() const
225 return parent() ? parent()->child( position()+1 ) : 0;
229 \brief Get previous sibling item.
231 \return previous sibling item or 0 if there are no any
233 SUIT_TreeModel::TreeItem* SUIT_TreeModel::TreeItem::prevSibling() const
235 return parent() ? parent()->child( position()-1 ) : 0;
239 \class SUIT_TreeModel::TreeSync
240 \brief Functor class for synchronizing data tree and tree model
241 when the data tree is changed outside the model.
245 class SUIT_TreeModel::TreeSync
248 TreeSync( SUIT_TreeModel* );
249 bool isEqual( const ObjPtr&, const ItemPtr& ) const;
250 ObjPtr nullSrc() const;
251 ItemPtr nullTrg() const;
252 ItemPtr createItem( const ObjPtr&, const ItemPtr&, const ItemPtr& ) const;
253 void updateItem( const ObjPtr&, const ItemPtr& ) const;
254 void deleteItemWithChildren( const ItemPtr& ) const;
255 QList<ObjPtr> children( const ObjPtr& ) const;
256 QList<ItemPtr> children( const ItemPtr& ) const;
257 ItemPtr parent( const ItemPtr& ) const;
259 bool needUpdate( const ItemPtr& ) const;
260 SUIT_TreeModel* myModel;
266 \param model tree model
268 SUIT_TreeModel::TreeSync::TreeSync( SUIT_TreeModel* model )
274 \brief Check if item corresponds to the specified data object.
276 \param obj data object
277 \param item tree item
278 \return \c true if item corresponds to the data object
280 bool SUIT_TreeModel::TreeSync::isEqual( const ObjPtr& obj, const ItemPtr& item ) const
282 bool isRoot = obj == myModel->root() && item == myModel->rootItem(),
283 isEq = obj && item && item->dataObject() == obj;
284 return isRoot || ( !obj && !item ) || isEq;
288 \brief Get null data object.
290 \return null data object
292 SUIT_TreeModel::ObjPtr SUIT_TreeModel::TreeSync::nullSrc() const
298 \brief Get null tree item.
300 \return null tree item
302 SUIT_TreeModel::ItemPtr SUIT_TreeModel::TreeSync::nullTrg() const
308 \brief Create an item corresponding to the specified data object.
310 \param obj data object
311 \param parent parent tree item
312 \param after tree item after each new one should be inserted
315 SUIT_TreeModel::ItemPtr SUIT_TreeModel::TreeSync::createItem( const ObjPtr& obj,
316 const ItemPtr& parent,
317 const ItemPtr& after ) const
319 ItemPtr item = myModel ? myModel->createItem( obj, parent, after ) : 0;
321 // Additional actions that can't be performed by the model, e.g. expanded state
328 \brief Update tree item.
330 \param obj reference data object
331 \param item tree item to be updated
333 void SUIT_TreeModel::TreeSync::updateItem( const ObjPtr& obj, const ItemPtr& item ) const
337 if ( item && needUpdate( item ) )
338 myModel->updateItem( item, false );
342 \brief Delete item with all children recursively.
344 \param item tree item
346 void SUIT_TreeModel::TreeSync::deleteItemWithChildren( const ItemPtr& item ) const
348 // NOTE: item is deleted inside removeItem()!
349 myModel->removeItem( item );
353 \brief Get all the children of the specified data object.
355 \param obj data object
356 \return list of the children
358 QList<SUIT_TreeModel::ObjPtr> SUIT_TreeModel::TreeSync::children( const ObjPtr& obj ) const
362 ch = obj->children();
367 \brief Get all the children of the specified tree item.
369 \param item tree item
370 \return list of the children
372 QList<SUIT_TreeModel::ItemPtr> SUIT_TreeModel::TreeSync::children( const ItemPtr& item ) const
376 ch = item->children();
381 \brief Get item which is the parent for the specified item.
383 \param item tree item
386 SUIT_TreeModel::ItemPtr SUIT_TreeModel::TreeSync::parent( const ItemPtr& item ) const
388 return item ? item->parent() : 0;
392 \brief Check if the tree item needs updating.
394 \param item tree item to be checked
395 \return \c true if item needs updating
397 \todo finalize this method
399 bool SUIT_TreeModel::TreeSync::needUpdate( const ItemPtr& item ) const
403 SUIT_DataObject* obj = item->dataObject();
405 // TODO: find simplified way to check if an item is not up-to-date:
406 // - use check-sum of various item data
407 // - use "LastModified" time stamp in data objects and tree items - hardly possible, for sometimes data objects do not know that data changes...
409 update = true; // TEMPORARY!!!
411 /* update = ( item->text( 0 ) != obj->name() ) || myBrowser->needToUpdateTexts( item );
414 // 2. check pixmap (compare serialNumber()-s)
415 QPixmap objPix = obj->icon();
416 const QPixmap* itemPix = item->pixmap( 0 );
417 update = ( objPix.isNull() && ( itemPix && !itemPix->isNull() ) ) ||
418 ( !objPix.isNull() && ( !itemPix || itemPix->isNull() ) );
419 if ( !update && !objPix.isNull() && itemPix && !itemPix->isNull() ) {
420 int aIconW = objPix.width();
423 double aScale = 20.0 / aIconW;
424 aM.scale( aScale, aScale );
425 objPix = objPix.xForm( aM );
427 update = ( objPix.serialNumber() != itemPix->serialNumber() );
436 \class SUIT_TreeModel
437 \brief Implementation of the model/view API based on the tree of SUIT_DataObject class
440 The SUIT_TreeModel class does not support insertion/removal of rows. It is synchronized
441 automatically with the tree of data objects used by SUIT-based applications to
442 expose their data in a hierarchical form to the user.
447 \param parent parent object
449 SUIT_TreeModel::SUIT_TreeModel( QObject* parent )
450 : QAbstractItemModel( parent ),
453 myAutoDeleteTree( false ),
454 myAutoUpdate( true ),
455 myUpdateModified( false )
462 \param root root data object
463 \param parent parent object
465 SUIT_TreeModel::SUIT_TreeModel( SUIT_DataObject* root, QObject* parent )
466 : QAbstractItemModel( parent ),
469 myAutoDeleteTree( false ),
470 myAutoUpdate( true ),
471 myUpdateModified( false )
479 SUIT_TreeModel::~SUIT_TreeModel()
481 if ( autoDeleteTree() ) {
482 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
483 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
484 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
485 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
486 SUIT_DataObject::disconnect( SIGNAL( modifed( SUIT_DataObject* ) ),
487 this, SLOT( onModified( SUIT_DataObject* ) ) );
495 \brief Register new column in the model
496 \param group_id - unique data object group identificator
497 \param name - translated column name
498 \param custom_id - custom column id that should be passed into method SUIT_DataObject::data()
500 void SUIT_TreeModel::registerColumn( const int group_id, const QString& name, const int custom_id )
503 for ( int i=0, n=myColumns.size(); i<n && !found; i++ ) {
504 if ( name == myColumns[i].myName ) {
505 myColumns[i].myIds.insert( group_id, custom_id );
512 inf.myIds.insert( group_id, custom_id );
513 inf.myAppropriate = Qtx::Shown;
514 inf.myHeaderFlags = Qtx::ShowAll;
515 int n = myColumns.size();
516 myColumns.resize( n+1 );
523 \brief Remove column from the model
525 Please take into account that column is removed only for given group_id, it means
526 that information of data objects with such group_id won't be shown.
527 If there is not any registered group_id for this column after removing, the column will be hidden
528 otherwise it continue to be shown
530 \param group_id - unique data object identificator allowing the classification of objects
531 \param name - translated column name
533 void SUIT_TreeModel::unregisterColumn( const int group_id, const QString& name )
535 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
536 if ( myColumns[i].myName == name ) {
537 myColumns[i].myIds.remove( group_id );
538 if ( myColumns[i].myIds.isEmpty() ) {
539 myColumns.remove( i );
548 \brief Change column icon.
550 \param name - column name
551 \param icon - new icon of the specified column
553 void SUIT_TreeModel::setColumnIcon( const QString& name, const QPixmap& icon )
555 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
556 if ( myColumns[i].myName == name ) {
557 myColumns[i].myIcon = icon;
564 \brief Get column icon.
566 \param name - column name
567 \return icon of the specified column
569 QPixmap SUIT_TreeModel::columnIcon( const QString& name ) const
572 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
573 if ( myColumns[i].myName == name ) {
574 res = myColumns[i].myIcon;
582 \brief Change appropriate status
584 Appropriate status determines if the column should appear in the tree view header popup menu
585 (to show/hide the column).
587 If appropriate status is not specified yet, the \c Shown value is taken,
588 it means that column should be always visible.
590 \param name - column name
591 \param appr - new appropriate status
593 void SUIT_TreeModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
595 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
596 if ( myColumns[i].myName == name && myColumns[i].myAppropriate != appr ) {
597 myColumns[i].myAppropriate = appr;
598 emit headerDataChanged( Qt::Horizontal, i, i );
605 \brief Check if the column should appear in the tree view header popup menu
606 (to show/hide the column).
608 Default implementation (if appropriate status is not specified yet)
609 returns \c Shown, it means that column should be always visible.
611 \param name - column name
612 \return appropriate status
614 Qtx::Appropriate SUIT_TreeModel::appropriate( const QString& name ) const
616 Qtx::Appropriate appr = Qtx::Shown;
617 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
618 if ( myColumns[i].myName == name ) {
619 appr = myColumns[i].myAppropriate;
628 \brief Set header flags.
630 These flags allow show in the header of the column text (name of the column),
631 icon or both text and icon.
633 \param name - column name
634 \param flags - header flags
637 void SUIT_TreeModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
639 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
640 if ( myColumns[i].myName == name && myColumns[i].myHeaderFlags != flags ) {
641 myColumns[i].myHeaderFlags = flags;
642 emit headerDataChanged( Qt::Horizontal, i, i );
649 \brief Get the header flags.
651 These flags allow show in the header of the column text (name of the column),
652 icon or both text and icon.
654 \param name - column name
657 Qtx::HeaderViewFlags SUIT_TreeModel::headerFlags( const QString& name ) const
659 Qtx::HeaderViewFlags flags;
660 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
661 if ( myColumns[i].myName == name ) {
662 flags = myColumns[i].myHeaderFlags;
670 \brief Set visibility state of the object.
672 \param id - column name
673 \param state - visible state
674 \param emitChanged - if set to false, blocks dataChanged() signal, this can be used to
675 prevent emitting dataChanged() several times for the same data object
677 void SUIT_TreeModel::setVisibilityState( const QString& id, Qtx::VisibilityState state, bool emitChanged )
679 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
680 if ( it != myVisibilityMap.end() && it.value() == state )
683 bool needSignal = false;
684 if ( state != Qtx::UnpresentableState ) {
685 myVisibilityMap.insert( id, state );
689 needSignal = myVisibilityMap.remove( id ) > 0;
691 if ( emitChanged && needSignal ) {
694 SUIT_DataObject* o = searcher()->findObject( id );
695 if ( o ) lst << index( o );
698 lst = match( index( 0, root()->customData( Qtx::IdType ).toInt() ), DisplayRole, id, 1, Qt::MatchExactly | Qt::MatchRecursive );
700 if ( !lst.isEmpty() ) {
701 QModelIndex idx = index( lst.first().row(), SUIT_DataObject::VisibilityId, lst.first().parent() );
702 emit dataChanged( idx, idx );
708 \brief Set visibility state for all objects.
710 \param state - visible state
712 void SUIT_TreeModel::setVisibilityStateForAll( Qtx::VisibilityState state )
714 foreach( QString id, myVisibilityMap.keys() )
715 setVisibilityState( id, state );
719 \brief Get visibility state of the object.
721 \param id - column name
722 \return visible state
724 Qtx::VisibilityState SUIT_TreeModel::visibilityState( const QString& id ) const
726 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
727 return it != myVisibilityMap.end() ? it.value() : Qtx::UnpresentableState;
731 \brief Get data tree root object.
732 \return data tree root
735 SUIT_DataObject* SUIT_TreeModel::root() const
741 \brief Set data tree root object.
742 \param r new data tree root
745 void SUIT_TreeModel::setRoot( SUIT_DataObject* r )
750 if ( autoDeleteTree() ) {
751 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
752 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
753 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
754 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
755 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
756 this, SLOT( onModified( SUIT_DataObject* ) ) );
760 QList<TreeItem*> items = myRootItem->children();
761 for ( QList<TreeItem*>::iterator anIt = items.begin(); anIt != items.end(); anIt++ )
774 \brief Get data for the specified model index and data role.
775 \param index model index
776 \param role data role
777 \return requested data
780 QVariant SUIT_TreeModel::data( const QModelIndex& index, int role ) const
782 if ( !index.isValid() )
785 SUIT_DataObject* obj = object( index );
792 int obj_group_id = obj->groupId();
793 const ColumnInfo& inf = myColumns[index.column()];
796 if( inf.myIds.contains( 0 ) )
798 if( inf.myIds.contains( obj_group_id ) )
799 id = inf.myIds[obj_group_id];
809 // data object text for the specified column
810 val = obj->text( id );
813 // data object text for the specified column (for editor)
814 val = obj->text( id );
816 case DecorationRole: {
818 if ( id == SUIT_DataObject::VisibilityId ) {
819 // for visibility column, icon is defined specifically (using data object id)
820 QString objId = objectId( index );
821 if ( myVisibilityMap.contains( objId ) ) {
822 // visibility status is defined -> return proper icon
823 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
824 val = ( myVisibilityMap.value( objId ) == Qtx::ShownState ) ?
825 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ) :
826 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_INVISIBLE" ) );
829 // visibility status is undefined -> no icon
834 // for other columns get icon from the object
835 val = obj->icon( id );
840 // data object tooltip for the specified column
841 val = obj->toolTip( id );
844 // data object status tip for the specified column
845 val = obj->statusTip( id );
848 // data object what's this info for the specified column
849 val = obj->whatsThis( id );
852 // data object font for the specified column
853 val = obj->font( id );
855 case TextAlignmentRole:
856 // data object text alignment for the specified column
857 val = obj->alignment( id );
860 // data background color for the specified column
861 c = obj->color( SUIT_DataObject::Background, id );
862 if( !c.isValid() ) // default value
863 c = QApplication::palette().color( QPalette::Base );
868 // data foreground (text) color for the specified column
869 c = obj->color( SUIT_DataObject::Foreground, id );
870 if( !c.isValid() ) // default value
871 c = QApplication::palette().color( QPalette::Foreground );
875 // editor background color for the specified column
876 c = obj->color( SUIT_DataObject::Base, id );
877 if( !c.isValid() ) // default value
878 c = QApplication::palette().color( QPalette::Base );
882 // editor foreground (text) color for the specified column
883 c = obj->color( SUIT_DataObject::Text, id );
884 if( !c.isValid() ) // default value
885 c = QApplication::palette().color( QPalette::Text );
889 // adta object highlighted background color for the specified column
890 c = obj->color( SUIT_DataObject::Highlight, id );
891 if( !c.isValid() ) // default value
892 c = QApplication::palette().color( QPalette::Highlight );
895 case HighlightedTextRole:
896 // data object highlighted foreground (text) color for the specified column
897 c = obj->color( SUIT_DataObject::HighlightedText, id );
898 if( !c.isValid() ) // default value
899 c = QApplication::palette().color( QPalette::HighlightedText );
903 // data object checked state for the specified column
904 // NOTE! three-state check is not supported currently
905 if( obj->isCheckable( id ) )
906 val = obj->isOn( id ) ? Qt::Checked : Qt::Unchecked;
910 // NOTE! not supported currently
914 } // ... switch ( role ) ...
915 } // ... if ( obj ) ...
920 \brief Set data for the specified model index and data role.
921 \param index model index
922 \param value new data value
923 \param role data role
924 \return \c true if data is set
927 bool SUIT_TreeModel::setData( const QModelIndex& index,
928 const QVariant& value, int role )
930 if ( index.isValid() && value.isValid() ) {
931 SUIT_DataObject* obj = object( index );
933 // NOTE! only 'check state' data is supported by default
937 if ( obj->isCheckable( index.column() ) ) {
938 obj->setOn( value.toBool(), index.column() );
939 emit( dataChanged( index, index ) );
944 QString val = value.toString();
945 bool mod = obj->name() != val;
946 if ( !val.isEmpty() && obj->setName(val) ) {
947 emit( dataChanged( index, index ) );
949 emit ( renamed(obj) );
960 return QAbstractItemModel::setData( index, value, role );
964 \brief Get data flags for specified model index.
965 \param index model index
968 Qt::ItemFlags SUIT_TreeModel::flags( const QModelIndex& index ) const
972 if (!index.isValid())
973 //return Qt::ItemIsDropEnabled; // items can be dropped into the top level of the model
976 SUIT_DataObject* obj = object(index);
979 // data object is enabled
980 if (obj->isEnabled())
981 f = f | Qt::ItemIsEnabled;
983 // data object is selectable
984 if (obj->isSelectable())
985 f = f | Qt::ItemIsSelectable;
987 // data object is checkable
988 if (obj->isCheckable(index.column()))
989 f = f | Qt::ItemIsUserCheckable;
991 // data object can be renamed
992 if (obj->renameAllowed(index.column()))
993 f = f | Qt::ItemIsEditable;
995 // data object can be dragged
996 if (obj->isDraggable())
997 f = f | Qt::ItemIsDragEnabled;
999 // another data object(s) can be dropped on this one
1000 if (obj->isDropAccepted())
1001 f = f | Qt::ItemIsDropEnabled;
1007 Qt::DropActions SUIT_TreeModel::supportedDropActions() const
1009 return Qt::CopyAction | Qt::MoveAction;
1013 \brief Get header data (can be used in any data view).
1014 \param column column number
1015 \param orientation header orientation
1016 \param role data role
1019 QVariant SUIT_TreeModel::headerData( int column, Qt::Orientation orientation, int role ) const
1022 // NOTE! only horizontal header is supported
1023 if ( root() && orientation == Qt::Horizontal )
1029 if((myColumns[column].myHeaderFlags & Qtx::ShowText) ||
1030 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1031 d = myColumns[column].myName;
1035 case DecorationRole:
1037 if((myColumns[column].myHeaderFlags & Qtx::ShowIcon) ||
1038 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1039 d = myColumns[column].myIcon;
1043 case AppropriateRole:
1044 // appropriate flag (can column be hidden via context popup menu)
1045 d = myColumns[column].myAppropriate;
1055 \brief Create model index.
1057 \param column data column
1058 \param parent parent model index
1061 QModelIndex SUIT_TreeModel::index( int row, int column,
1062 const QModelIndex& parent ) const
1064 if( hasIndex( row, column, parent ) )
1066 TreeItem* parentItem = treeItem( parent );
1069 TreeItem* childItem = parentItem->child( row );
1071 return createIndex( row, column, childItem );
1074 return QModelIndex();
1078 \brief Get parent model index.
1079 \param index model index
1080 \return parent model index
1082 QModelIndex SUIT_TreeModel::parent( const QModelIndex& index ) const
1084 if ( !index.isValid() )
1085 return QModelIndex();
1087 TreeItem* childItem = treeItem( index );
1088 TreeItem* parentItem = childItem ? childItem->parent() : 0;
1090 if ( !parentItem || parentItem == rootItem() )
1091 return QModelIndex();
1093 return createIndex( parentItem->position(), 0, parentItem );
1097 \brief Get number of data columns.
1098 \param parent parent model index (not used)
1099 \return data columns number
1102 int SUIT_TreeModel::columnCount( const QModelIndex& /*parent*/ ) const
1104 return myColumns.size();
1108 \brief Get number of data rows (children of the specified model index).
1109 \param parent parent model index
1110 \return data rows (children) number
1113 int SUIT_TreeModel::rowCount( const QModelIndex& parent ) const
1115 // Commented by rnv in the frame of the
1116 // "20830: EDF 1357 GUI : Hide/Show Icon" imp
1117 // if ( parent.column() > 0 )
1120 TreeItem* parentItem = treeItem( parent );
1122 return parentItem ? parentItem->childCount() : 0;
1126 \brief Get data object by the specified model index.
1127 \param index model index
1128 \return data object corresponding to the model index
1130 SUIT_DataObject* SUIT_TreeModel::object( const QModelIndex& index ) const
1132 return object( treeItem( index ) );
1136 \brief Get model index by the specified data object.
1137 \param obj data object
1138 \param column data object column
1141 QModelIndex SUIT_TreeModel::index( const SUIT_DataObject* obj, int column ) const
1143 if ( obj == root() )
1144 return QModelIndex();
1146 TreeItem* item = treeItem( obj );
1148 return item ? createIndex( item->position(), column, item ) : QModelIndex();
1152 \brief Get 'auto-delete data tree' flag value.
1153 \return 'auto-delete data tree' flag value
1154 \sa setAutoDeleteTree()
1156 bool SUIT_TreeModel::autoDeleteTree() const
1158 return myAutoDeleteTree;
1162 \brief Set 'auto-delete data tree' flag value.
1164 If this flag is set to \c true, the data tree is deleted when
1165 the tree model is destroyed. Default value for this flag is \c false.
1167 \param on 'auto-delete data tree' flag value
1168 \sa autoDeleteTree()
1170 void SUIT_TreeModel::setAutoDeleteTree( const bool on )
1172 myAutoDeleteTree = on;
1176 \brief Get 'auto-update tree' flag value.
1177 \return 'auto-update tree' flag value
1178 \sa setAutoUpdate(), updateTree()
1180 bool SUIT_TreeModel::autoUpdate() const
1182 return myAutoUpdate;
1186 \brief Set 'auto-update tree' flag value.
1188 If this flag is set to \c true (by default), the model is updated
1189 automatically when data tree is changed.
1191 \param on 'auto-update tree' flag value
1192 \sa autoUpdate(), updateTree()
1194 void SUIT_TreeModel::setAutoUpdate( const bool on )
1196 if ( myAutoUpdate == on )
1199 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1200 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1201 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1202 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1203 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
1204 this, SLOT( onModified( SUIT_DataObject* ) ) );
1207 if ( myAutoUpdate ) {
1208 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1209 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1210 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1211 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1212 SUIT_DataObject::connect( SIGNAL( modified( SUIT_DataObject* ) ),
1213 this, SLOT( onModified( SUIT_DataObject* ) ) );
1220 \brief Get 'updateModified' flag value.
1221 \return 'updateModified' flag value
1223 bool SUIT_TreeModel::updateModified() const
1225 return myUpdateModified;
1228 \brief Set 'updateModified' flag value.
1229 \param on 'updateModified' flag value
1231 void SUIT_TreeModel::setUpdateModified(const bool on)
1233 myUpdateModified=on;
1237 \brief Check if the specified column supports custom sorting.
1238 \param column column index on which data is being sorted
1239 \return \c true if column requires custom sorting
1242 bool SUIT_TreeModel::customSorting( const int column ) const
1244 return root() ? root()->customSorting( column ) : false;
1247 void SUIT_TreeModel::forgetObject( const SUIT_DataObject* obj )
1249 removeItem( treeItem( obj ) );
1253 \brief Compares two model indexes for the sorting purposes.
1255 This method is called only for those columns for which customSorting()
1256 method returns \c true.
1258 \param left first index to compare
1259 \param right second index to compare
1260 \return result of the comparison
1263 bool SUIT_TreeModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
1265 QVariant ldata = data( left );
1266 QVariant rdata = data( right );
1267 return root() ? root()->compare( ldata, rdata, left.column() ) : false;
1271 \brief Get item delegate for the model.
1272 \return new item delegate
1274 QAbstractItemDelegate* SUIT_TreeModel::delegate() const
1276 return new SUIT_ItemDelegate( const_cast<SUIT_TreeModel*>( this ) );
1280 void SUIT_TreeModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index) {
1281 int obj_group_id = obj->groupId();
1282 const ColumnInfo& inf = myColumns[index.column()];
1285 if( inf.myIds.contains( 0 ) )
1287 if( inf.myIds.contains( obj_group_id ) )
1288 id = inf.myIds[obj_group_id];
1289 emit clicked(obj, id);
1293 \brief Update tree model.
1295 Call this method when data tree is changed outside the model.
1296 If the 'auto-update' flag is set to \c true, the model
1297 is updated automatically when the data tree is changed.
1299 \param index starting index for the updating
1302 void SUIT_TreeModel::updateTree( const QModelIndex& index )
1304 updateTree( object( index ) );
1308 void SUIT_TreeModel::updateTreeModel(SUIT_DataObject* obj,TreeItem* item)
1312 int nobjchild=obj->childCount();
1313 SUIT_DataObject* sobj=obj->childObject(kobj);
1314 TreeItem* sitem = item->child(kitem);
1316 while(kobj < nobjchild)
1321 sitem=createItemAtPos(sobj,item,kitem);
1322 updateTreeModel(sobj,sitem);
1325 sobj=obj->childObject(kobj);
1326 sitem = item->child(kitem);
1328 else if(sitem->dataObject() != sobj)
1334 sitem = item->child(kitem);
1339 sitem=createItemAtPos(sobj,item,kitem);
1340 updateTreeModel(sobj,sitem);
1343 sobj=obj->childObject(kobj);
1344 sitem = item->child(kitem);
1349 //obj and item are synchronised : go to next ones
1350 updateTreeModel(sobj,sitem);
1351 if(sobj->modified()) updateItem(sitem, true);
1355 sobj=obj->childObject(kobj);
1356 sitem = item->child(kitem);
1359 //remove remaining items
1360 for(int i = item->childCount(); i > kitem;i--)
1362 sitem = item->child(i-1);
1368 \brief Update tree model.
1370 Call this method when data tree is changed outside the model.
1371 If the 'auto-update' flag is set to \c true, the model
1372 is updated automatically when the data tree is changed.
1374 \param obj starting data object for the updating
1377 void SUIT_TreeModel::updateTree( SUIT_DataObject* obj )
1382 else if ( obj->root() != root() )
1385 if(updateModified())
1387 updateTreeModel(obj,treeItem( obj ));
1391 synchronize<ObjPtr,ItemPtr,SUIT_TreeModel::TreeSync>( obj,
1393 SUIT_TreeModel::TreeSync( this ) );
1395 emit modelUpdated();
1399 \brief Initialize tree model.
1401 void SUIT_TreeModel::initialize()
1403 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1404 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1405 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1406 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1407 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
1408 this, SLOT( onModified( SUIT_DataObject* ) ) );
1409 if ( autoUpdate() ) {
1410 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1411 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1412 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1413 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1414 SUIT_DataObject::connect( SIGNAL( modified( SUIT_DataObject* ) ),
1415 this, SLOT( onModified( SUIT_DataObject* ) ) );
1418 myItems.clear(); // ????? is it really necessary
1421 myRootItem = new TreeItem( 0 );
1423 registerColumn( 0, QObject::tr( "NAME_COLUMN" ), SUIT_DataObject::NameId );
1425 QString visCol = QObject::tr( "VISIBILITY_COLUMN" );
1426 registerColumn( 0, visCol, SUIT_DataObject::VisibilityId );
1428 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1429 setColumnIcon( visCol, resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ));
1430 setHeaderFlags( visCol, Qtx::ShowIcon);
1436 \brief Get root tree item.
1437 \return root tree item
1439 SUIT_TreeModel::TreeItem* SUIT_TreeModel::rootItem() const
1445 \brief Get tree item corresponding to the specified model index.
1446 \param index model index
1447 \return tree item or root item if index is invalid
1449 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const QModelIndex& index ) const
1451 return index.isValid() ? static_cast<TreeItem*>( index.internalPointer() ) : rootItem();
1455 \brief Get tree item corresponding to the specified data object.
1456 \param obj data object
1457 \return tree item or 0 if there is no tree item corresponding to \a obj
1459 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const SUIT_DataObject* obj ) const
1463 if ( obj == root() )
1465 else if ( myItems.contains( const_cast<SUIT_DataObject*>( obj ) ) )
1466 item = myItems[ const_cast<SUIT_DataObject*>( obj ) ];
1472 \brief Get data object corresponding to the specified tree item.
1473 \param item tree item
1474 \return data object or 0 if there is no data object corresponding to \a item
1476 SUIT_DataObject* SUIT_TreeModel::object( const SUIT_TreeModel::TreeItem* item ) const
1478 if ( item == rootItem() )
1481 SUIT_DataObject* obj = item ? item->dataObject() : 0;
1482 return myItems.contains( obj ) ? obj : 0;
1486 \brief Get unique object identifier
1488 Object identifier is customized via the Qtx::IdType custom data
1490 \param index model index
1491 \return object identifier or null string if it isn't specified
1492 \sa SUIT_DataObject::customData()
1494 QString SUIT_TreeModel::objectId( const QModelIndex& index ) const
1497 if ( index.isValid() ) {
1498 SUIT_DataObject* obj = object( index );
1500 int anId = obj->customData( Qtx::IdType ).toInt();
1501 objId = data( createIndex( index.row(), anId, index.internalPointer() ) ).toString();
1508 \brief Create an item corresponding to the data object.
1509 \param obj source data object
1510 \param parent parent tree item
1511 \param after tree item after which new item should be inserted
1512 \return created tree item or 0 if item could not be created
1514 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItem( SUIT_DataObject* obj,
1515 SUIT_TreeModel::TreeItem* parent,
1516 SUIT_TreeModel::TreeItem* after )
1521 SUIT_DataObject* parentObj = object( parent );
1522 QModelIndex parentIdx = index( parentObj );
1524 SUIT_DataObject* afterObj = after ? object( after ) : 0;
1525 int row = afterObj ? afterObj->position() + 1 : 0;
1527 beginInsertRows( parentIdx, row, row );
1529 myItems[ obj ] = new TreeItem( obj, parent, after );
1531 for(int pos=row;pos < parent->childCount();pos++)
1532 parent->child(pos)->setPosition(pos);
1536 obj->setModified(false);
1538 return myItems[ obj ];
1542 \brief Create an item corresponding to the data object.
1543 \param obj source data object
1544 \param parent parent tree item
1545 \param pos tree item position into which new item should be inserted
1546 \return created tree item or 0 if item could not be created
1548 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItemAtPos( SUIT_DataObject* obj,
1549 SUIT_TreeModel::TreeItem* parent,
1555 SUIT_DataObject* parentObj = object( parent );
1556 QModelIndex parentIdx = index( parentObj );
1559 SUIT_TreeModel::TreeItem* after = pos>0 ? parent->child(pos-1) : 0 ;
1561 beginInsertRows( parentIdx, row, row );
1563 SUIT_TreeModel::TreeItem* item = new TreeItem( obj, parent, after );
1564 myItems[ obj ] = item;
1566 for(int ppos=row;ppos < parent->childCount();ppos++)
1567 parent->child(ppos)->setPosition(ppos);
1571 obj->setModified(false);
1577 \brief Update tree item.
1578 \param item tree item to be updated
1579 \param emitLayoutChanged if signal about changed layout should be emitted
1581 void SUIT_TreeModel::updateItem( SUIT_TreeModel::TreeItem* item, bool emitLayoutChanged )
1586 SUIT_DataObject* obj = object( item );
1590 // update all columns corresponding to the given data object
1591 /*To avoid crashes we should update any persistent model indexes before emitting layoutChanged(). In other words, when the structure changes:
1592 - emit layoutAboutToBeChanged
1593 - Remember the QModelIndex that will change
1594 - call changePersistentIndex()
1595 - emit layoutChanged
1598 emit layoutAboutToBeChanged();
1600 // Remember the QModelIndex that will change
1601 QModelIndexList fromIndexes;
1602 QModelIndexList toIndexes;
1603 for (int i = 0; i < columnCount() - 1; ++i) {
1604 fromIndexes.append( index( obj, i ));
1605 toIndexes.append(QModelIndex());
1607 //changePersistentIndexList(fromIndexes, toIndexes); // Limitation: can lead to loss of selection
1609 emit dataChanged( toIndexes.first(), toIndexes.last() );
1610 obj->setModified(false);
1611 if ( emitLayoutChanged )
1612 emit layoutChanged();
1616 \brief Remove tree item (recursively).
1617 \param item tree item to be removed
1619 void SUIT_TreeModel::removeItem( SUIT_TreeModel::TreeItem* item )
1624 // Remove list view items from <myItems> recursively for all children.
1625 // Otherwise, "delete item" line below will destroy all item's children,
1626 // and <myItems> will contain invalid pointers
1627 while( item->childCount() )
1628 removeItem( item->child( 0 ) );
1630 SUIT_DataObject* obj = object( item );
1632 // Warning! obj can be deleted at this point!
1634 TreeItem* parent=item->parent();
1635 SUIT_DataObject* parentObj = object( parent );
1636 QModelIndex parentIdx = index( parentObj, 0 );
1637 int row = item->position();
1639 beginRemoveRows( parentIdx, row, row );
1640 myItems.remove( obj );
1642 if ( obj == root() )
1646 parent->removeChild( item );
1647 for(int pos=row;pos < parent->childCount();pos++)
1648 parent->child(pos)->setPosition(pos);
1657 \brief Called when the data object is inserted to the tree.
1658 \param object data object being inserted
1659 \param parent parent data object
1661 void SUIT_TreeModel::onInserted( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1664 updateTree( parent );
1668 \brief Called when the data object is removed from the tree.
1669 \param object data object being removed
1670 \param parent parent data object
1672 void SUIT_TreeModel::onRemoved( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1675 updateTree( parent );
1679 \brief Called when the data object is modified. TreeSync is not used here for maximum efficiency.
1680 It is assumed that it is up to the application to decide when its data objects are modified.
1681 \param obj data object that has been modified
1683 void SUIT_TreeModel::onModified( SUIT_DataObject* obj )
1687 QModelIndex firstIdx = index( obj, 0 );
1688 QModelIndex lastIdx = index( obj, columnCount() - 1 );
1689 emit dataChanged( firstIdx, lastIdx );
1690 obj->setModified(false);
1695 \brief Drag and Drop support.
1697 QStringList SUIT_TreeModel::mimeTypes() const
1700 types << "application/vnd.text.list";
1705 \brief Called when the data objects are exported(dragged) from the tree.
1706 \param indexes the list of exported objects
1708 QMimeData* SUIT_TreeModel::mimeData( const QModelIndexList& indexes ) const
1710 QMimeData* mimeData = new QMimeData();
1711 QByteArray encodedData;
1713 QDataStream stream( &encodedData, QIODevice::WriteOnly );
1715 foreach ( QModelIndex index, indexes ) {
1716 QString id = objectId( index );
1717 // we have to check only 0 column in order to avoid repeating items in the drag object
1718 // - QTreeView tries to drag indices for all visible columns
1719 if ( index.isValid() && index.column() == 0 && !id.isEmpty() )
1723 mimeData->setData( "application/vnd.text.list", encodedData );
1727 bool SUIT_TreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action,
1728 int row, int column, const QModelIndex& parent )
1730 if ( action == Qt::IgnoreAction )
1731 // do nothing with data
1734 if ( !data->hasFormat( "application/vnd.text.list" ) )
1735 // not supported data dropped
1738 if ( !parent.isValid() )
1739 // dropping into the top level of the model is not allowed
1742 // get parent object
1743 SUIT_DataObject* pobj = object( parent );
1748 // decode mime data and collect data objects being dropped
1749 QByteArray encodedData = data->data( "application/vnd.text.list" );
1750 QDataStream stream( &encodedData, QIODevice::ReadOnly );
1752 DataObjectList objects;
1754 while ( !stream.atEnd() ) {
1757 if ( !id.isEmpty() && searcher() ) {
1758 SUIT_DataObject* obj = searcher()->findObject( id );
1759 if ( obj ) objects << obj;
1764 emit dropped( objects, pobj, row, action );
1766 // return true if there's any to drop
1767 return !objects.isEmpty();
1771 \class SUIT_ProxyModel
1772 \brief Proxy model which can be used above the SUIT_TreeModel class
1773 to enable custom sorting/filtering of the data.
1775 The SUIT_TreeModel class does not support custom sorting/filtering of the data.
1776 To use these features, the SUIT_ProxyModel class can be used as top-level
1777 wrapper for the SUIT_DataObject-based data tree model.
1782 \param parent parent object
1784 SUIT_ProxyModel::SUIT_ProxyModel( QObject* parent )
1785 : QSortFilterProxyModel( parent ),
1786 mySortingEnabled( true )
1788 SUIT_TreeModel* model = new SUIT_TreeModel( this );
1789 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1790 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL(clicked( SUIT_DataObject*, int ) ) );
1791 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1792 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1793 connect( model, SIGNAL( renamed( SUIT_DataObject* ) ), this, SIGNAL( renamed( SUIT_DataObject* ) ) );
1794 setSourceModel( model );
1795 setDynamicSortFilter( true );
1800 \param root root data object
1801 \param parent parent object
1803 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_DataObject* root, QObject* parent )
1804 : QSortFilterProxyModel( parent ),
1805 mySortingEnabled( true )
1807 SUIT_TreeModel* model = new SUIT_TreeModel( root, this );
1808 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1809 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1810 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1811 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1812 connect( model, SIGNAL( renamed( SUIT_DataObject* ) ), this, SIGNAL( renamed( SUIT_DataObject* ) ) );
1813 setSourceModel( model );
1814 setDynamicSortFilter( true );
1819 \param model tree model
1820 \param parent parent object
1822 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_AbstractModel* model, QObject* parent )
1823 : QSortFilterProxyModel( parent ),
1824 mySortingEnabled( true )
1826 connect( *model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1827 connect( *model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1828 connect( *model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1829 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1830 connect( *model, SIGNAL( renamed( SUIT_DataObject* ) ), this, SIGNAL( rename( SUIT_DataObject* ) ) );
1831 setSourceModel( *model );
1832 setDynamicSortFilter( true );
1838 SUIT_ProxyModel::~SUIT_ProxyModel()
1843 \brief Get data tree root object.
1844 \return data tree root
1847 SUIT_DataObject* SUIT_ProxyModel::root() const
1849 return treeModel() ? treeModel()->root() : 0;
1853 \brief Set data tree root object.
1854 \param r new data tree root
1857 void SUIT_ProxyModel::setRoot( SUIT_DataObject* r )
1860 treeModel()->setRoot( r );
1864 \brief Get data object by the specified model index.
1865 \param index model index
1866 \return data object corresponding to the model index
1868 SUIT_DataObject* SUIT_ProxyModel::object( const QModelIndex& index ) const
1870 return treeModel() ? treeModel()->object( mapToSource( index ) ) : 0;
1874 \brief Get model index by the specified data object.
1875 \param obj data object
1876 \param column data object column
1879 QModelIndex SUIT_ProxyModel::index( const SUIT_DataObject* obj, int column ) const
1881 return treeModel() ? mapFromSource( treeModel()->index( obj, column ) ) : QModelIndex();
1885 \brief Get 'auto-delete data tree' flag value.
1886 \return 'auto-delete data tree' flag value
1887 \sa setAutoDeleteTree()
1889 bool SUIT_ProxyModel::autoDeleteTree() const
1891 return treeModel() ? treeModel()->autoDeleteTree() : false;
1895 \brief Set 'auto-delete data tree' flag value.
1897 If this flag is set to \c true, the data tree is deleted when
1898 the tree model is destroyed. Default value for this flag is \c false.
1900 \param on 'auto-delete data tree' flag value
1901 \sa autoDeleteTree()
1903 void SUIT_ProxyModel::setAutoDeleteTree( const bool on )
1906 treeModel()->setAutoDeleteTree( on );
1910 \brief Get 'auto-update tree' flag value.
1911 \return 'auto-update tree' flag value
1912 \sa setAutoUpdate(), updateTree()
1914 bool SUIT_ProxyModel::autoUpdate() const
1916 return treeModel() ? treeModel()->autoUpdate() : false;
1920 \brief Get 'updateModified' flag value.
1921 \return 'updateModified' flag value
1923 bool SUIT_ProxyModel::updateModified() const
1925 return treeModel() ? treeModel()->updateModified() : false;
1928 \brief Set 'updateModified' flag value.
1930 If this flag is set to \c true (default=false), the model is updated by updateTreeModel that
1931 uses the isModified flag to update only modified objects
1933 \param on 'updateModified' flag value
1935 void SUIT_ProxyModel::setUpdateModified( const bool on )
1938 treeModel()->setUpdateModified( on );
1942 \brief Set 'auto-update tree' flag value.
1944 If this flag is set to \c true (by default), the model is updated
1945 automatically when data tree is changed.
1947 \param on 'auto-update tree' flag value
1948 \sa autoUpdate(), updateTree()
1950 void SUIT_ProxyModel::setAutoUpdate( const bool on )
1953 treeModel()->setAutoUpdate( on );
1957 \brief Check if sorting is enabled.
1958 \return \c true if sorting is enabled
1959 \sa setSortingEnabled()
1961 bool SUIT_ProxyModel::isSortingEnabled() const
1963 return mySortingEnabled;
1966 SUIT_DataSearcher* SUIT_ProxyModel::searcher() const
1968 return treeModel() ? treeModel()->searcher() : 0;
1971 void SUIT_ProxyModel::setSearcher( SUIT_DataSearcher* s )
1973 if ( treeModel() ) treeModel()->setSearcher( s );
1977 \brief Get item delegate for the model.
1978 \return new item delegate
1980 QAbstractItemDelegate* SUIT_ProxyModel::delegate() const
1982 return treeModel() ? treeModel()->delegate() : 0;
1986 \brief Update tree model.
1988 Call this method when data tree is changed outside the model.
1989 If the 'auto-update' flag is set to \c true, the model
1990 is updated automatically when the data tree is changed.
1992 \param index starting index for the updating
1995 void SUIT_ProxyModel::updateTree( const QModelIndex& index )
1998 treeModel()->updateTree( mapToSource( index ) );
2002 \brief Update tree model.
2004 Call this method when data tree is changed outside the model.
2005 If the 'auto-update' flag is set to \c true, the model
2006 is updated automatically when the data tree is changed.
2008 \param obj starting data object for the updating
2011 void SUIT_ProxyModel::updateTree( SUIT_DataObject* obj )
2014 treeModel()->updateTree( obj );
2017 void SUIT_ProxyModel::forgetObject( const SUIT_DataObject* obj )
2020 treeModel()->forgetObject( obj );
2024 \brief Compares two model indexes for the sorting purposes.
2025 \param left first index to compare
2026 \param right second index to compare
2027 \return result of the comparison
2029 bool SUIT_ProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
2031 if ( !isSortingEnabled() && left.isValid() && right.isValid() ) {
2032 return left.row() < right.row();
2034 if ( treeModel() && treeModel()->customSorting( left.column() ) ) {
2035 return treeModel()->lessThan( left, right );
2037 return QSortFilterProxyModel::lessThan( left, right );
2041 \brief Check if the specified column supports custom sorting.
2042 \param column column index on which data is being sorted
2043 \return \c true if column requires custom sorting
2046 bool SUIT_ProxyModel::customSorting( const int column ) const
2048 return treeModel() ? treeModel()->customSorting( column ) : false;
2052 \brief Enable/disable sorting.
2053 \param enabled new flag state
2054 \sa isSortingEnabled()
2056 void SUIT_ProxyModel::setSortingEnabled( bool enabled )
2058 mySortingEnabled = enabled;
2063 \brief Get tree model.
2066 SUIT_AbstractModel* SUIT_ProxyModel::treeModel() const
2068 return dynamic_cast<SUIT_AbstractModel*>( sourceModel() );
2073 \param sourceRow row index of the source data model
2074 \param sourceParent parent model index of the source data model
2075 \return \c true if the specified row should be filtered out (i.e. not displayed) or \c false otherwise
2077 bool SUIT_ProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
2079 SUIT_DataObject* o = treeModel()->object( sourceModel()->index( sourceRow, 0, sourceParent ) );
2080 SUIT_DataObject* p = o ? o->parent() : 0;
2081 return ( !p || p->expandable() ) && o && o->isVisible();
2085 \brief Register new column in the model
2086 \param group_id - unique data object identificator allowing the classification of objects
2087 \param name - translated column name
2088 \param custom_id - custom column id that should be passed into method SUIT_DataObject::data()
2090 void SUIT_ProxyModel::registerColumn( const int group_id, const QString& name, const int custom_id )
2093 treeModel()->registerColumn( group_id, name, custom_id );
2097 \brief Remove column from the model
2099 Please take into account that column is removed only for given group_id, it means
2100 that information of data objects with such group_id won't be shown.
2101 If there is not any registered group_id for this column after removing, the column will be hidden
2102 otherwise it continue to be shown
2104 \param group_id - unique data object identificator allowing the classification of objects
2105 \param name - translated column name
2107 void SUIT_ProxyModel::unregisterColumn( const int group_id, const QString& name )
2110 treeModel()->unregisterColumn( group_id, name );
2114 \brief Change column icon.
2116 \param name - column name
2117 \param icon - new icon of the specified column
2119 void SUIT_ProxyModel::setColumnIcon( const QString& name, const QPixmap& icon )
2122 treeModel()->setColumnIcon( name, icon );
2126 \brief Get column icon.
2128 \param name - column name
2129 \return icon of the specified column
2131 QPixmap SUIT_ProxyModel::columnIcon( const QString& name ) const
2133 return treeModel() ? treeModel()->columnIcon( name ) : QPixmap();
2137 \brief Change appropriate status
2139 Appropriate status determines if the column should appear in the tree view header popup menu
2140 (to show/hide the column).
2142 If appropriate status is not specified yet, the \c Shown value is taken,
2143 it means that column should be always visible.
2145 \param name - column name
2146 \param appr - new appropriate status
2148 void SUIT_ProxyModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
2151 treeModel()->setAppropriate( name, appr );
2155 \brief Check if the column should appear in the tree view header popup menu
2156 (to show/hide the column).
2158 Default implementation (if appropriate status is not specified yet)
2159 returns \c Shown, it means that column should be always visible.
2161 \param name - column name
2162 \return appropriate status
2164 Qtx::Appropriate SUIT_ProxyModel::appropriate( const QString& name ) const
2166 return treeModel() ? treeModel()->appropriate( name ) : Qtx::Shown;
2170 \brief Set header flags.
2172 These flags allow show in the header of the column text (name of the column),
2173 icon or both text and icon.
2175 \param name - column name
2176 \param flags - header flags
2179 void SUIT_ProxyModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
2182 treeModel()->setHeaderFlags(name, flags);
2186 \brief Get the header flags.
2188 These flags allow show in the header of the column text (name of the column),
2189 icon or both text and icon.
2191 \param name - column name
2192 \return header flags
2194 Qtx::HeaderViewFlags SUIT_ProxyModel::headerFlags( const QString& name ) const
2196 return treeModel() ? treeModel()->headerFlags( name ) : Qtx::ShowAll;
2200 \brief Set visibility state of the object.
2202 \param id - column name
2203 \param state - visible state
2204 \param emitChanged - if set to false, blocks dataChanged() signal, this can be used to
2205 prevent emitting dataChanged() several times for the same data object
2207 void SUIT_ProxyModel::setVisibilityState(const QString& id, Qtx::VisibilityState state, bool emitChanged ) {
2209 treeModel()->setVisibilityState(id,state,emitChanged);
2213 \brief Set visibility state for all objects.
2215 \param id - column name
2216 \param state - visible state
2218 void SUIT_ProxyModel::setVisibilityStateForAll(Qtx::VisibilityState state)
2221 treeModel()->setVisibilityStateForAll(state);
2225 \brief Get visibility state of the object.
2227 \param id - column name
2228 \return visible state
2230 Qtx::VisibilityState SUIT_ProxyModel::visibilityState(const QString& id) const
2232 return treeModel() ? treeModel()->visibilityState(id) : Qtx::UnpresentableState;
2235 void SUIT_ProxyModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index)
2238 treeModel()->emitClicked(obj,index);
2242 \class SUIT_ItemDelegate
2243 \brief An SUIT_DataObject-based item delegate class.
2245 This class can be used to render the SUIT_DataObject-based item
2246 in the widgets like QTreeView and others.
2247 Refer to the Qt 4 documentation, model/view architecture
2248 section for more details).
2253 \param parent parent object
2255 SUIT_ItemDelegate::SUIT_ItemDelegate( QObject* parent )
2256 : QItemDelegate( parent )
2261 \brief Render the item in the widget.
2263 Customizes the item colors for the specific roles.
2265 \param painter painter
2266 \param option painting option
2267 \param index model index being rendered
2269 void SUIT_ItemDelegate::paint( QPainter* painter,
2270 const QStyleOptionViewItem& option,
2271 const QModelIndex& index ) const
2273 QStyleOptionViewItem opt = option;
2274 if ( index.isValid() ) {
2275 // Note: we check into account only custom roles; other roles are process
2276 // correctly by the QItemDelegate class
2277 QVariant val = index.data( SUIT_TreeModel::BaseColorRole );
2278 if ( val.isValid() && val.value<QColor>().isValid() ) {
2279 QColor aBase = val.value<QColor>();
2280 aBase.setAlpha( 0 );
2281 opt.palette.setBrush( QPalette::Base, val.value<QColor>() );
2283 val = index.data( SUIT_TreeModel::TextColorRole );
2284 if ( val.isValid() && val.value<QColor>().isValid() )
2285 opt.palette.setBrush( QPalette::Text, val.value<QColor>() );
2286 val = index.data( SUIT_TreeModel::HighlightRole );
2287 if ( val.isValid() && val.value<QColor>().isValid() )
2288 opt.palette.setBrush( QPalette::Highlight, val.value<QColor>() );
2289 val = index.data( SUIT_TreeModel::HighlightedTextRole );
2290 if ( val.isValid() && val.value<QColor>().isValid() )
2291 opt.palette.setBrush( QPalette::HighlightedText, val.value<QColor>() );
2293 QItemDelegate::paint( painter, opt, index );
2296 QSize SUIT_ItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
2298 QSize size = QItemDelegate::sizeHint ( option, index );
2299 #if QT_VERSION >= 0x040500
2300 size.setHeight( size.height() + 1 );