1 // Copyright (C) 2007-2019 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 )
504 for ( int i=0, n=myColumns.size(); i<n && !found; i++ ) {
505 if ( name == myColumns[i].myName ) {
506 myColumns[i].myIds.insert( group_id, custom_id );
513 inf.myIds.insert( group_id, custom_id );
514 inf.myAppropriate = Qtx::Shown;
515 inf.myHeaderFlags = Qtx::ShowAll;
516 int n = myColumns.size();
517 myColumns.resize( n+1 );
524 \brief Remove column from the model
526 Please take into account that column is removed only for given group_id, it means
527 that information of data objects with such group_id won't be shown.
528 If there is not any registered group_id for this column after removing, the column will be hidden
529 otherwise it continue to be shown
531 \param group_id - unique data object identificator allowing the classification of objects
532 \param name - translated column name
534 void SUIT_TreeModel::unregisterColumn( const int group_id, const QString& name )
536 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
538 if ( myColumns[i].myName == name ) {
539 myColumns[i].myIds.remove( group_id );
540 if ( myColumns[i].myIds.isEmpty() ) {
541 myColumns.remove( i );
550 \brief Change column icon.
552 \param name - column name
553 \param icon - new icon of the specified column
555 void SUIT_TreeModel::setColumnIcon( const QString& name, const QPixmap& icon )
557 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
558 if ( myColumns[i].myName == name ) {
559 myColumns[i].myIcon = icon;
566 \brief Get column icon.
568 \param name - column name
569 \return icon of the specified column
571 QPixmap SUIT_TreeModel::columnIcon( const QString& name ) const
574 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
575 if ( myColumns[i].myName == name ) {
576 res = myColumns[i].myIcon;
584 \brief Change appropriate status
586 Appropriate status determines if the column should appear in the tree view header popup menu
587 (to show/hide the column).
589 If appropriate status is not specified yet, the \c Shown value is taken,
590 it means that column should be always visible.
592 \param name - column name
593 \param appr - new appropriate status
595 void SUIT_TreeModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
597 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
598 if ( myColumns[i].myName == name && myColumns[i].myAppropriate != appr ) {
599 myColumns[i].myAppropriate = appr;
600 emit headerDataChanged( Qt::Horizontal, i, i );
607 \brief Check if the column should appear in the tree view header popup menu
608 (to show/hide the column).
610 Default implementation (if appropriate status is not specified yet)
611 returns \c Shown, it means that column should be always visible.
613 \param name - column name
614 \return appropriate status
616 Qtx::Appropriate SUIT_TreeModel::appropriate( const QString& name ) const
618 Qtx::Appropriate appr = Qtx::Shown;
619 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
620 if ( myColumns[i].myName == name ) {
621 appr = myColumns[i].myAppropriate;
630 \brief Set header flags.
632 These flags allow show in the header of the column text (name of the column),
633 icon or both text and icon.
635 \param name - column name
636 \param flags - header flags
639 void SUIT_TreeModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
641 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
642 if ( myColumns[i].myName == name && myColumns[i].myHeaderFlags != flags ) {
643 myColumns[i].myHeaderFlags = flags;
644 emit headerDataChanged( Qt::Horizontal, i, i );
651 \brief Get the header flags.
653 These flags allow show in the header of the column text (name of the column),
654 icon or both text and icon.
656 \param name - column name
659 Qtx::HeaderViewFlags SUIT_TreeModel::headerFlags( const QString& name ) const
661 Qtx::HeaderViewFlags flags;
662 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
663 if ( myColumns[i].myName == name ) {
664 flags = myColumns[i].myHeaderFlags;
672 \brief Set visibility state of the object.
674 \param id - column name
675 \param state - visible state
676 \param emitChanged - if set to false, blocks dataChanged() signal, this can be used to
677 prevent emitting dataChanged() several times for the same data object
679 void SUIT_TreeModel::setVisibilityState( const QString& id, Qtx::VisibilityState state, bool emitChanged )
681 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
682 if ( it != myVisibilityMap.end() && it.value() == state )
685 bool needSignal = false;
686 if ( state != Qtx::UnpresentableState ) {
687 myVisibilityMap.insert( id, state );
691 needSignal = myVisibilityMap.remove( id ) > 0;
693 if ( emitChanged && needSignal ) {
696 SUIT_DataObject* o = searcher()->findObject( id );
697 if ( o ) lst << index( o );
700 lst = match( index( 0, root()->customData( Qtx::IdType ).toInt() ), DisplayRole, id, 1, Qt::MatchExactly | Qt::MatchRecursive );
702 if ( !lst.isEmpty() ) {
703 QModelIndex idx = index( lst.first().row(), SUIT_DataObject::VisibilityId, lst.first().parent() );
704 emit dataChanged( idx, idx );
710 \brief Set visibility state for all objects.
712 \param state - visible state
714 void SUIT_TreeModel::setVisibilityStateForAll( Qtx::VisibilityState state )
716 foreach( QString id, myVisibilityMap.keys() )
717 setVisibilityState( id, state );
721 \brief Get visibility state of the object.
723 \param id - column name
724 \return visible state
726 Qtx::VisibilityState SUIT_TreeModel::visibilityState( const QString& id ) const
728 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
729 return it != myVisibilityMap.end() ? it.value() : Qtx::UnpresentableState;
733 \brief Get data tree root object.
734 \return data tree root
737 SUIT_DataObject* SUIT_TreeModel::root() const
743 \brief Set data tree root object.
744 \param r new data tree root
747 void SUIT_TreeModel::setRoot( SUIT_DataObject* r )
753 if ( autoDeleteTree() ) {
754 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
755 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
756 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
757 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
758 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
759 this, SLOT( onModified( SUIT_DataObject* ) ) );
763 QList<TreeItem*> items = myRootItem->children();
764 for ( QList<TreeItem*>::iterator anIt = items.begin(); anIt != items.end(); anIt++ )
777 \brief Get data for the specified model index and data role.
778 \param index model index
779 \param role data role
780 \return requested data
783 QVariant SUIT_TreeModel::data( const QModelIndex& index, int role ) const
785 if ( !index.isValid() )
788 SUIT_DataObject* obj = object( index );
795 int obj_group_id = obj->groupId();
796 const ColumnInfo& inf = myColumns[index.column()];
799 if( inf.myIds.contains( 0 ) )
801 if( inf.myIds.contains( obj_group_id ) )
802 id = inf.myIds[obj_group_id];
812 // data object text for the specified column
813 val = obj->text( id );
816 // data object text for the specified column (for editor)
817 val = obj->text( id );
819 case DecorationRole: {
821 if ( id == SUIT_DataObject::VisibilityId ) {
822 // for visibility column, icon is defined specifically (using data object id)
823 QString objId = objectId( index );
824 if ( myVisibilityMap.contains( objId ) ) {
825 // visibility status is defined -> return proper icon
826 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
827 val = ( myVisibilityMap.value( objId ) == Qtx::ShownState ) ?
828 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ) :
829 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_INVISIBLE" ) );
832 // visibility status is undefined -> no icon
837 // for other columns get icon from the object
838 val = obj->icon( id );
843 // data object tooltip for the specified column
844 val = obj->toolTip( id );
847 // data object status tip for the specified column
848 val = obj->statusTip( id );
851 // data object what's this info for the specified column
852 val = obj->whatsThis( id );
855 // data object font for the specified column
856 val = obj->font( id );
858 case TextAlignmentRole:
859 // data object text alignment for the specified column
860 val = obj->alignment( id );
863 // data background color for the specified column
864 c = obj->color( SUIT_DataObject::Background, id );
865 if( !c.isValid() ) // default value
866 c = QApplication::palette().color( QPalette::Base );
871 // data foreground (text) color for the specified column
872 c = obj->color( SUIT_DataObject::Foreground, id );
873 if( !c.isValid() ) // default value
874 c = QApplication::palette().color( QPalette::Foreground );
878 // editor background color for the specified column
879 c = obj->color( SUIT_DataObject::Base, id );
880 if( !c.isValid() ) // default value
881 c = QApplication::palette().color( QPalette::Base );
885 // editor foreground (text) color for the specified column
886 c = obj->color( SUIT_DataObject::Text, id );
887 if( !c.isValid() ) // default value
888 c = QApplication::palette().color( QPalette::Text );
892 // adta object highlighted background color for the specified column
893 c = obj->color( SUIT_DataObject::Highlight, id );
894 if( !c.isValid() ) // default value
895 c = QApplication::palette().color( QPalette::Highlight );
898 case HighlightedTextRole:
899 // data object highlighted foreground (text) color for the specified column
900 c = obj->color( SUIT_DataObject::HighlightedText, id );
901 if( !c.isValid() ) // default value
902 c = QApplication::palette().color( QPalette::HighlightedText );
906 // data object checked state for the specified column
907 // NOTE! three-state check is not supported currently
908 if( obj->isCheckable( id ) )
909 val = obj->isOn( id ) ? Qt::Checked : Qt::Unchecked;
913 // NOTE! not supported currently
917 } // ... switch ( role ) ...
918 } // ... if ( obj ) ...
923 \brief Set data for the specified model index and data role.
924 \param index model index
925 \param value new data value
926 \param role data role
927 \return \c true if data is set
930 bool SUIT_TreeModel::setData( const QModelIndex& index,
931 const QVariant& value, int role )
933 if ( index.isValid() && value.isValid() ) {
934 SUIT_DataObject* obj = object( index );
936 // NOTE! only 'check state' data is supported by default
940 if ( obj->isCheckable( index.column() ) ) {
941 obj->setOn( value.toBool(), index.column() );
942 emit( dataChanged( index, index ) );
947 QString val = value.toString();
948 bool mod = obj->name() != val;
949 if ( !val.isEmpty() && obj->setName(val) ) {
950 emit( dataChanged( index, index ) );
952 emit ( renamed(obj) );
963 return QAbstractItemModel::setData( index, value, role );
967 \brief Get data flags for specified model index.
968 \param index model index
971 Qt::ItemFlags SUIT_TreeModel::flags( const QModelIndex& index ) const
975 if (!index.isValid())
976 //return Qt::ItemIsDropEnabled; // items can be dropped into the top level of the model
979 SUIT_DataObject* obj = object(index);
982 // data object is enabled
983 if (obj->isEnabled())
984 f = f | Qt::ItemIsEnabled;
986 // data object is selectable
987 if (obj->isSelectable())
988 f = f | Qt::ItemIsSelectable;
990 // data object is checkable
991 if (obj->isCheckable(index.column()))
992 f = f | Qt::ItemIsUserCheckable;
994 // data object can be renamed
995 if (obj->renameAllowed(index.column()))
996 f = f | Qt::ItemIsEditable;
998 // data object can be dragged
999 if (obj->isDraggable())
1000 f = f | Qt::ItemIsDragEnabled;
1002 // another data object(s) can be dropped on this one
1003 if (obj->isDropAccepted())
1004 f = f | Qt::ItemIsDropEnabled;
1010 Qt::DropActions SUIT_TreeModel::supportedDropActions() const
1012 return Qt::CopyAction | Qt::MoveAction;
1016 \brief Get header data (can be used in any data view).
1017 \param column column number
1018 \param orientation header orientation
1019 \param role data role
1022 QVariant SUIT_TreeModel::headerData( int column, Qt::Orientation orientation, int role ) const
1025 // NOTE! only horizontal header is supported
1026 if ( root() && orientation == Qt::Horizontal )
1032 if((myColumns[column].myHeaderFlags & Qtx::ShowText) ||
1033 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1034 d = myColumns[column].myName;
1038 case DecorationRole:
1040 if((myColumns[column].myHeaderFlags & Qtx::ShowIcon) ||
1041 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1042 d = myColumns[column].myIcon;
1046 case AppropriateRole:
1047 // appropriate flag (can column be hidden via context popup menu)
1048 d = myColumns[column].myAppropriate;
1058 \brief Create model index.
1060 \param column data column
1061 \param parent parent model index
1064 QModelIndex SUIT_TreeModel::index( int row, int column,
1065 const QModelIndex& parent ) const
1067 if( hasIndex( row, column, parent ) )
1069 TreeItem* parentItem = treeItem( parent );
1072 TreeItem* childItem = parentItem->child( row );
1074 return createIndex( row, column, childItem );
1077 return QModelIndex();
1081 \brief Get parent model index.
1082 \param index model index
1083 \return parent model index
1085 QModelIndex SUIT_TreeModel::parent( const QModelIndex& index ) const
1087 if ( !index.isValid() )
1088 return QModelIndex();
1090 TreeItem* childItem = treeItem( index );
1091 TreeItem* parentItem = childItem ? childItem->parent() : 0;
1093 if ( !parentItem || parentItem == rootItem() )
1094 return QModelIndex();
1096 return createIndex( parentItem->position(), 0, parentItem );
1100 \brief Get number of data columns.
1101 \param parent parent model index (not used)
1102 \return data columns number
1105 int SUIT_TreeModel::columnCount( const QModelIndex& /*parent*/ ) const
1107 return myColumns.size();
1111 \brief Get number of data rows (children of the specified model index).
1112 \param parent parent model index
1113 \return data rows (children) number
1116 int SUIT_TreeModel::rowCount( const QModelIndex& parent ) const
1118 // Commented by rnv in the frame of the
1119 // "20830: EDF 1357 GUI : Hide/Show Icon" imp
1120 // if ( parent.column() > 0 )
1123 TreeItem* parentItem = treeItem( parent );
1125 return parentItem ? parentItem->childCount() : 0;
1129 \brief Get data object by the specified model index.
1130 \param index model index
1131 \return data object corresponding to the model index
1133 SUIT_DataObject* SUIT_TreeModel::object( const QModelIndex& index ) const
1135 return object( treeItem( index ) );
1139 \brief Get model index by the specified data object.
1140 \param obj data object
1141 \param column data object column
1144 QModelIndex SUIT_TreeModel::index( const SUIT_DataObject* obj, int column ) const
1146 if ( obj == root() )
1147 return QModelIndex();
1149 TreeItem* item = treeItem( obj );
1151 return item ? createIndex( item->position(), column, item ) : QModelIndex();
1155 \brief Get 'auto-delete data tree' flag value.
1156 \return 'auto-delete data tree' flag value
1157 \sa setAutoDeleteTree()
1159 bool SUIT_TreeModel::autoDeleteTree() const
1161 return myAutoDeleteTree;
1165 \brief Set 'auto-delete data tree' flag value.
1167 If this flag is set to \c true, the data tree is deleted when
1168 the tree model is destroyed. Default value for this flag is \c false.
1170 \param on 'auto-delete data tree' flag value
1171 \sa autoDeleteTree()
1173 void SUIT_TreeModel::setAutoDeleteTree( const bool on )
1175 myAutoDeleteTree = on;
1179 \brief Get 'auto-update tree' flag value.
1180 \return 'auto-update tree' flag value
1181 \sa setAutoUpdate(), updateTree()
1183 bool SUIT_TreeModel::autoUpdate() const
1185 return myAutoUpdate;
1189 \brief Set 'auto-update tree' flag value.
1191 If this flag is set to \c true (by default), the model is updated
1192 automatically when data tree is changed.
1194 \param on 'auto-update tree' flag value
1195 \sa autoUpdate(), updateTree()
1197 void SUIT_TreeModel::setAutoUpdate( const bool on )
1199 if ( myAutoUpdate == on )
1202 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1203 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1204 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1205 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1206 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
1207 this, SLOT( onModified( SUIT_DataObject* ) ) );
1210 if ( myAutoUpdate ) {
1211 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1212 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1213 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1214 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1215 SUIT_DataObject::connect( SIGNAL( modified( SUIT_DataObject* ) ),
1216 this, SLOT( onModified( SUIT_DataObject* ) ) );
1223 \brief Get 'updateModified' flag value.
1224 \return 'updateModified' flag value
1226 bool SUIT_TreeModel::updateModified() const
1228 return myUpdateModified;
1231 \brief Set 'updateModified' flag value.
1232 \param on 'updateModified' flag value
1234 void SUIT_TreeModel::setUpdateModified(const bool on)
1236 myUpdateModified=on;
1240 \brief Check if the specified column supports custom sorting.
1241 \param column column index on which data is being sorted
1242 \return \c true if column requires custom sorting
1245 bool SUIT_TreeModel::customSorting( const int column ) const
1247 return root() ? root()->customSorting( column ) : false;
1250 void SUIT_TreeModel::forgetObject( const SUIT_DataObject* obj )
1252 removeItem( treeItem( obj ) );
1256 \brief Compares two model indexes for the sorting purposes.
1258 This method is called only for those columns for which customSorting()
1259 method returns \c true.
1261 \param left first index to compare
1262 \param right second index to compare
1263 \return result of the comparison
1266 bool SUIT_TreeModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
1268 QVariant ldata = data( left );
1269 QVariant rdata = data( right );
1270 return root() ? root()->compare( ldata, rdata, left.column() ) : false;
1274 \brief Get item delegate for the model.
1275 \return new item delegate
1277 QAbstractItemDelegate* SUIT_TreeModel::delegate() const
1279 return new SUIT_ItemDelegate( const_cast<SUIT_TreeModel*>( this ) );
1283 void SUIT_TreeModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index) {
1284 int obj_group_id = obj->groupId();
1285 const ColumnInfo& inf = myColumns[index.column()];
1288 if( inf.myIds.contains( 0 ) )
1290 if( inf.myIds.contains( obj_group_id ) )
1291 id = inf.myIds[obj_group_id];
1292 emit clicked(obj, id);
1296 \brief Update tree model.
1298 Call this method when data tree is changed outside the model.
1299 If the 'auto-update' flag is set to \c true, the model
1300 is updated automatically when the data tree is changed.
1302 \param index starting index for the updating
1305 void SUIT_TreeModel::updateTree( const QModelIndex& index )
1307 updateTree( object( index ) );
1311 void SUIT_TreeModel::updateTreeModel(SUIT_DataObject* obj,TreeItem* item)
1315 int nobjchild=obj->childCount();
1316 SUIT_DataObject* sobj=obj->childObject(kobj);
1317 TreeItem* sitem = item->child(kitem);
1319 while(kobj < nobjchild)
1324 sitem=createItemAtPos(sobj,item,kitem);
1325 updateTreeModel(sobj,sitem);
1328 sobj=obj->childObject(kobj);
1329 sitem = item->child(kitem);
1331 else if(sitem->dataObject() != sobj)
1337 sitem = item->child(kitem);
1342 sitem=createItemAtPos(sobj,item,kitem);
1343 updateTreeModel(sobj,sitem);
1346 sobj=obj->childObject(kobj);
1347 sitem = item->child(kitem);
1352 //obj and item are synchronised : go to next ones
1353 updateTreeModel(sobj,sitem);
1354 if(sobj->modified()) updateItem(sitem, true);
1358 sobj=obj->childObject(kobj);
1359 sitem = item->child(kitem);
1362 //remove remaining items
1363 for(int i = item->childCount(); i > kitem;i--)
1365 sitem = item->child(i-1);
1371 \brief Update tree model.
1373 Call this method when data tree is changed outside the model.
1374 If the 'auto-update' flag is set to \c true, the model
1375 is updated automatically when the data tree is changed.
1377 \param obj starting data object for the updating
1380 void SUIT_TreeModel::updateTree( SUIT_DataObject* obj )
1385 else if ( obj->root() != root() )
1388 if(updateModified())
1390 updateTreeModel(obj,treeItem( obj ));
1394 synchronize<ObjPtr,ItemPtr,SUIT_TreeModel::TreeSync>( obj,
1396 SUIT_TreeModel::TreeSync( this ) );
1398 emit modelUpdated();
1402 \brief Initialize tree model.
1404 void SUIT_TreeModel::initialize()
1406 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1407 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1408 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1409 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1410 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
1411 this, SLOT( onModified( SUIT_DataObject* ) ) );
1412 if ( autoUpdate() ) {
1413 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1414 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1415 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1416 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1417 SUIT_DataObject::connect( SIGNAL( modified( SUIT_DataObject* ) ),
1418 this, SLOT( onModified( SUIT_DataObject* ) ) );
1421 myItems.clear(); // ????? is it really necessary
1424 myRootItem = new TreeItem( 0 );
1426 registerColumn( 0, QObject::tr( "NAME_COLUMN" ), SUIT_DataObject::NameId );
1428 QString visCol = QObject::tr( "VISIBILITY_COLUMN" );
1429 registerColumn( 0, visCol, SUIT_DataObject::VisibilityId );
1431 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1432 setColumnIcon( visCol, resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ));
1433 setHeaderFlags( visCol, Qtx::ShowIcon);
1439 \brief Get root tree item.
1440 \return root tree item
1442 SUIT_TreeModel::TreeItem* SUIT_TreeModel::rootItem() const
1448 \brief Get tree item corresponding to the specified model index.
1449 \param index model index
1450 \return tree item or root item if index is invalid
1452 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const QModelIndex& index ) const
1454 return index.isValid() ? static_cast<TreeItem*>( index.internalPointer() ) : rootItem();
1458 \brief Get tree item corresponding to the specified data object.
1459 \param obj data object
1460 \return tree item or 0 if there is no tree item corresponding to \a obj
1462 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const SUIT_DataObject* obj ) const
1466 if ( obj == root() )
1468 else if ( myItems.contains( const_cast<SUIT_DataObject*>( obj ) ) )
1469 item = myItems[ const_cast<SUIT_DataObject*>( obj ) ];
1475 \brief Get data object corresponding to the specified tree item.
1476 \param item tree item
1477 \return data object or 0 if there is no data object corresponding to \a item
1479 SUIT_DataObject* SUIT_TreeModel::object( const SUIT_TreeModel::TreeItem* item ) const
1481 if ( item == rootItem() )
1484 SUIT_DataObject* obj = item ? item->dataObject() : 0;
1485 return myItems.contains( obj ) ? obj : 0;
1489 \brief Get unique object identifier
1491 Object identifier is customized via the Qtx::IdType custom data
1493 \param index model index
1494 \return object identifier or null string if it isn't specified
1495 \sa SUIT_DataObject::customData()
1497 QString SUIT_TreeModel::objectId( const QModelIndex& index ) const
1500 if ( index.isValid() ) {
1501 SUIT_DataObject* obj = object( index );
1503 int anId = obj->customData( Qtx::IdType ).toInt();
1504 objId = data( createIndex( index.row(), anId, index.internalPointer() ) ).toString();
1511 \brief Create an item corresponding to the data object.
1512 \param obj source data object
1513 \param parent parent tree item
1514 \param after tree item after which new item should be inserted
1515 \return created tree item or 0 if item could not be created
1517 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItem( SUIT_DataObject* obj,
1518 SUIT_TreeModel::TreeItem* parent,
1519 SUIT_TreeModel::TreeItem* after )
1524 SUIT_DataObject* parentObj = object( parent );
1525 QModelIndex parentIdx = index( parentObj );
1527 SUIT_DataObject* afterObj = after ? object( after ) : 0;
1528 int row = afterObj ? afterObj->position() + 1 : 0;
1530 beginInsertRows( parentIdx, row, row );
1532 myItems[ obj ] = new TreeItem( obj, parent, after );
1534 for(int pos=row;pos < parent->childCount();pos++)
1535 parent->child(pos)->setPosition(pos);
1539 obj->setModified(false);
1541 return myItems[ obj ];
1545 \brief Create an item corresponding to the data object.
1546 \param obj source data object
1547 \param parent parent tree item
1548 \param pos tree item position into which new item should be inserted
1549 \return created tree item or 0 if item could not be created
1551 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItemAtPos( SUIT_DataObject* obj,
1552 SUIT_TreeModel::TreeItem* parent,
1558 SUIT_DataObject* parentObj = object( parent );
1559 QModelIndex parentIdx = index( parentObj );
1562 SUIT_TreeModel::TreeItem* after = pos>0 ? parent->child(pos-1) : 0 ;
1564 beginInsertRows( parentIdx, row, row );
1566 SUIT_TreeModel::TreeItem* item = new TreeItem( obj, parent, after );
1567 myItems[ obj ] = item;
1569 for(int ppos=row;ppos < parent->childCount();ppos++)
1570 parent->child(ppos)->setPosition(ppos);
1574 obj->setModified(false);
1580 \brief Update tree item.
1581 \param item tree item to be updated
1582 \param emitLayoutChanged if signal about changed layout should be emitted
1584 void SUIT_TreeModel::updateItem( SUIT_TreeModel::TreeItem* item, bool emitLayoutChanged )
1589 SUIT_DataObject* obj = object( item );
1593 // update all columns corresponding to the given data object
1594 /*To avoid crashes we should update any persistent model indexes before emitting layoutChanged(). In other words, when the structure changes:
1595 - emit layoutAboutToBeChanged
1596 - Remember the QModelIndex that will change
1597 - call changePersistentIndex()
1598 - emit layoutChanged
1601 emit layoutAboutToBeChanged();
1603 // Remember the QModelIndex that will change
1604 QModelIndexList fromIndexes;
1605 QModelIndexList toIndexes;
1606 for (int i = 0; i < columnCount() - 1; ++i) {
1607 fromIndexes.append( index( obj, i ));
1608 toIndexes.append(QModelIndex());
1610 //changePersistentIndexList(fromIndexes, toIndexes); // Limitation: can lead to loss of selection
1612 emit dataChanged( toIndexes.first(), toIndexes.last() );
1613 obj->setModified(false);
1614 if ( emitLayoutChanged )
1615 emit layoutChanged();
1619 \brief Remove tree item (recursively).
1620 \param item tree item to be removed
1622 void SUIT_TreeModel::removeItem( SUIT_TreeModel::TreeItem* item )
1627 // Remove list view items from <myItems> recursively for all children.
1628 // Otherwise, "delete item" line below will destroy all item's children,
1629 // and <myItems> will contain invalid pointers
1630 while( item->childCount() )
1631 removeItem( item->child( 0 ) );
1633 SUIT_DataObject* obj = object( item );
1635 // Warning! obj can be deleted at this point!
1637 TreeItem* parent=item->parent();
1638 SUIT_DataObject* parentObj = object( parent );
1639 QModelIndex parentIdx = index( parentObj, 0 );
1640 int row = item->position();
1642 beginRemoveRows( parentIdx, row, row );
1643 myItems.remove( obj );
1645 if ( obj == root() )
1649 parent->removeChild( item );
1650 for(int pos=row;pos < parent->childCount();pos++)
1651 parent->child(pos)->setPosition(pos);
1660 \brief Called when the data object is inserted to the tree.
1661 \param object data object being inserted
1662 \param parent parent data object
1664 void SUIT_TreeModel::onInserted( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1667 updateTree( parent );
1671 \brief Called when the data object is removed from the tree.
1672 \param object data object being removed
1673 \param parent parent data object
1675 void SUIT_TreeModel::onRemoved( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1678 updateTree( parent );
1682 \brief Called when the data object is modified. TreeSync is not used here for maximum efficiency.
1683 It is assumed that it is up to the application to decide when its data objects are modified.
1684 \param obj data object that has been modified
1686 void SUIT_TreeModel::onModified( SUIT_DataObject* obj )
1690 QModelIndex firstIdx = index( obj, 0 );
1691 QModelIndex lastIdx = index( obj, columnCount() - 1 );
1692 emit dataChanged( firstIdx, lastIdx );
1693 obj->setModified(false);
1698 \brief Drag and Drop support.
1700 QStringList SUIT_TreeModel::mimeTypes() const
1703 types << "application/vnd.text.list";
1708 \brief Called when the data objects are exported(dragged) from the tree.
1709 \param indexes the list of exported objects
1711 QMimeData* SUIT_TreeModel::mimeData( const QModelIndexList& indexes ) const
1713 QMimeData* mimeData = new QMimeData();
1714 QByteArray encodedData;
1716 QDataStream stream( &encodedData, QIODevice::WriteOnly );
1718 foreach ( QModelIndex index, indexes ) {
1719 QString id = objectId( index );
1720 // we have to check only 0 column in order to avoid repeating items in the drag object
1721 // - QTreeView tries to drag indices for all visible columns
1722 if ( index.isValid() && index.column() == 0 && !id.isEmpty() )
1726 mimeData->setData( "application/vnd.text.list", encodedData );
1730 bool SUIT_TreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action,
1731 int row, int column, const QModelIndex& parent )
1733 if ( action == Qt::IgnoreAction )
1734 // do nothing with data
1737 if ( !data->hasFormat( "application/vnd.text.list" ) )
1738 // not supported data dropped
1741 if ( !parent.isValid() )
1742 // dropping into the top level of the model is not allowed
1745 // get parent object
1746 SUIT_DataObject* pobj = object( parent );
1751 // decode mime data and collect data objects being dropped
1752 QByteArray encodedData = data->data( "application/vnd.text.list" );
1753 QDataStream stream( &encodedData, QIODevice::ReadOnly );
1755 DataObjectList objects;
1757 while ( !stream.atEnd() ) {
1760 if ( !id.isEmpty() && searcher() ) {
1761 SUIT_DataObject* obj = searcher()->findObject( id );
1762 if ( obj ) objects << obj;
1767 emit dropped( objects, pobj, row, action );
1769 // return true if there's any to drop
1770 return !objects.isEmpty();
1774 \class SUIT_ProxyModel
1775 \brief Proxy model which can be used above the SUIT_TreeModel class
1776 to enable custom sorting/filtering of the data.
1778 The SUIT_TreeModel class does not support custom sorting/filtering of the data.
1779 To use these features, the SUIT_ProxyModel class can be used as top-level
1780 wrapper for the SUIT_DataObject-based data tree model.
1785 \param parent parent object
1787 SUIT_ProxyModel::SUIT_ProxyModel( QObject* parent )
1788 : QSortFilterProxyModel( parent ),
1789 mySortingEnabled( true )
1791 SUIT_TreeModel* model = new SUIT_TreeModel( this );
1792 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1793 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL(clicked( SUIT_DataObject*, int ) ) );
1794 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1795 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1796 connect( model, SIGNAL( renamed( SUIT_DataObject* ) ), this, SIGNAL( renamed( SUIT_DataObject* ) ) );
1797 setSourceModel( model );
1798 setDynamicSortFilter( true );
1803 \param root root data object
1804 \param parent parent object
1806 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_DataObject* root, QObject* parent )
1807 : QSortFilterProxyModel( parent ),
1808 mySortingEnabled( true )
1810 SUIT_TreeModel* model = new SUIT_TreeModel( root, this );
1811 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1812 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1813 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1814 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1815 connect( model, SIGNAL( renamed( SUIT_DataObject* ) ), this, SIGNAL( renamed( SUIT_DataObject* ) ) );
1816 setSourceModel( model );
1817 setDynamicSortFilter( true );
1822 \param model tree model
1823 \param parent parent object
1825 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_AbstractModel* model, QObject* parent )
1826 : QSortFilterProxyModel( parent ),
1827 mySortingEnabled( true )
1829 connect( *model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1830 connect( *model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1831 connect( *model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1832 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1833 connect( *model, SIGNAL( renamed( SUIT_DataObject* ) ), this, SIGNAL( renamed( SUIT_DataObject* ) ) );
1834 setSourceModel( *model );
1835 setDynamicSortFilter( true );
1841 SUIT_ProxyModel::~SUIT_ProxyModel()
1846 \brief Get data tree root object.
1847 \return data tree root
1850 SUIT_DataObject* SUIT_ProxyModel::root() const
1852 return treeModel() ? treeModel()->root() : 0;
1856 \brief Set data tree root object.
1857 \param r new data tree root
1860 void SUIT_ProxyModel::setRoot( SUIT_DataObject* r )
1863 treeModel()->setRoot( r );
1867 \brief Get data object by the specified model index.
1868 \param index model index
1869 \return data object corresponding to the model index
1871 SUIT_DataObject* SUIT_ProxyModel::object( const QModelIndex& index ) const
1873 return treeModel() ? treeModel()->object( mapToSource( index ) ) : 0;
1877 \brief Get model index by the specified data object.
1878 \param obj data object
1879 \param column data object column
1882 QModelIndex SUIT_ProxyModel::index( const SUIT_DataObject* obj, int column ) const
1884 return treeModel() ? mapFromSource( treeModel()->index( obj, column ) ) : QModelIndex();
1888 \brief Get 'auto-delete data tree' flag value.
1889 \return 'auto-delete data tree' flag value
1890 \sa setAutoDeleteTree()
1892 bool SUIT_ProxyModel::autoDeleteTree() const
1894 return treeModel() ? treeModel()->autoDeleteTree() : false;
1898 \brief Set 'auto-delete data tree' flag value.
1900 If this flag is set to \c true, the data tree is deleted when
1901 the tree model is destroyed. Default value for this flag is \c false.
1903 \param on 'auto-delete data tree' flag value
1904 \sa autoDeleteTree()
1906 void SUIT_ProxyModel::setAutoDeleteTree( const bool on )
1909 treeModel()->setAutoDeleteTree( on );
1913 \brief Get 'auto-update tree' flag value.
1914 \return 'auto-update tree' flag value
1915 \sa setAutoUpdate(), updateTree()
1917 bool SUIT_ProxyModel::autoUpdate() const
1919 return treeModel() ? treeModel()->autoUpdate() : false;
1923 \brief Get 'updateModified' flag value.
1924 \return 'updateModified' flag value
1926 bool SUIT_ProxyModel::updateModified() const
1928 return treeModel() ? treeModel()->updateModified() : false;
1931 \brief Set 'updateModified' flag value.
1933 If this flag is set to \c true (default=false), the model is updated by updateTreeModel that
1934 uses the isModified flag to update only modified objects
1936 \param on 'updateModified' flag value
1938 void SUIT_ProxyModel::setUpdateModified( const bool on )
1941 treeModel()->setUpdateModified( on );
1945 \brief Set 'auto-update tree' flag value.
1947 If this flag is set to \c true (by default), the model is updated
1948 automatically when data tree is changed.
1950 \param on 'auto-update tree' flag value
1951 \sa autoUpdate(), updateTree()
1953 void SUIT_ProxyModel::setAutoUpdate( const bool on )
1956 treeModel()->setAutoUpdate( on );
1960 \brief Check if sorting is enabled.
1961 \return \c true if sorting is enabled
1962 \sa setSortingEnabled()
1964 bool SUIT_ProxyModel::isSortingEnabled() const
1966 return mySortingEnabled;
1969 SUIT_DataSearcher* SUIT_ProxyModel::searcher() const
1971 return treeModel() ? treeModel()->searcher() : 0;
1974 void SUIT_ProxyModel::setSearcher( SUIT_DataSearcher* s )
1976 if ( treeModel() ) treeModel()->setSearcher( s );
1980 \brief Get item delegate for the model.
1981 \return new item delegate
1983 QAbstractItemDelegate* SUIT_ProxyModel::delegate() const
1985 return treeModel() ? treeModel()->delegate() : 0;
1989 \brief Update tree model.
1991 Call this method when data tree is changed outside the model.
1992 If the 'auto-update' flag is set to \c true, the model
1993 is updated automatically when the data tree is changed.
1995 \param index starting index for the updating
1998 void SUIT_ProxyModel::updateTree( const QModelIndex& index )
2001 treeModel()->updateTree( mapToSource( index ) );
2005 \brief Update tree model.
2007 Call this method when data tree is changed outside the model.
2008 If the 'auto-update' flag is set to \c true, the model
2009 is updated automatically when the data tree is changed.
2011 \param obj starting data object for the updating
2014 void SUIT_ProxyModel::updateTree( SUIT_DataObject* obj )
2017 treeModel()->updateTree( obj );
2020 void SUIT_ProxyModel::forgetObject( const SUIT_DataObject* obj )
2023 treeModel()->forgetObject( obj );
2027 \brief Compares two model indexes for the sorting purposes.
2028 \param left first index to compare
2029 \param right second index to compare
2030 \return result of the comparison
2032 bool SUIT_ProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
2034 if ( !isSortingEnabled() && left.isValid() && right.isValid() ) {
2035 return left.row() < right.row();
2037 if ( treeModel() && treeModel()->customSorting( left.column() ) ) {
2038 return treeModel()->lessThan( left, right );
2040 return QSortFilterProxyModel::lessThan( left, right );
2044 \brief Check if the specified column supports custom sorting.
2045 \param column column index on which data is being sorted
2046 \return \c true if column requires custom sorting
2049 bool SUIT_ProxyModel::customSorting( const int column ) const
2051 return treeModel() ? treeModel()->customSorting( column ) : false;
2055 \brief Enable/disable sorting.
2056 \param enabled new flag state
2057 \sa isSortingEnabled()
2059 void SUIT_ProxyModel::setSortingEnabled( bool enabled )
2061 mySortingEnabled = enabled;
2066 \brief Get tree model.
2069 SUIT_AbstractModel* SUIT_ProxyModel::treeModel() const
2071 return dynamic_cast<SUIT_AbstractModel*>( sourceModel() );
2076 \param sourceRow row index of the source data model
2077 \param sourceParent parent model index of the source data model
2078 \return \c true if the specified row should be filtered out (i.e. not displayed) or \c false otherwise
2080 bool SUIT_ProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
2082 SUIT_DataObject* o = treeModel()->object( sourceModel()->index( sourceRow, 0, sourceParent ) );
2083 SUIT_DataObject* p = o ? o->parent() : 0;
2084 return ( !p || p->expandable() ) && o && o->isVisible();
2088 \brief Register new column in the model
2089 \param group_id - unique data object identificator allowing the classification of objects
2090 \param name - translated column name
2091 \param custom_id - custom column id that should be passed into method SUIT_DataObject::data()
2093 void SUIT_ProxyModel::registerColumn( const int group_id, const QString& name, const int custom_id )
2096 treeModel()->registerColumn( group_id, name, custom_id );
2100 \brief Remove column from the model
2102 Please take into account that column is removed only for given group_id, it means
2103 that information of data objects with such group_id won't be shown.
2104 If there is not any registered group_id for this column after removing, the column will be hidden
2105 otherwise it continue to be shown
2107 \param group_id - unique data object identificator allowing the classification of objects
2108 \param name - translated column name
2110 void SUIT_ProxyModel::unregisterColumn( const int group_id, const QString& name )
2113 treeModel()->unregisterColumn( group_id, name );
2117 \brief Change column icon.
2119 \param name - column name
2120 \param icon - new icon of the specified column
2122 void SUIT_ProxyModel::setColumnIcon( const QString& name, const QPixmap& icon )
2125 treeModel()->setColumnIcon( name, icon );
2129 \brief Get column icon.
2131 \param name - column name
2132 \return icon of the specified column
2134 QPixmap SUIT_ProxyModel::columnIcon( const QString& name ) const
2136 return treeModel() ? treeModel()->columnIcon( name ) : QPixmap();
2140 \brief Change appropriate status
2142 Appropriate status determines if the column should appear in the tree view header popup menu
2143 (to show/hide the column).
2145 If appropriate status is not specified yet, the \c Shown value is taken,
2146 it means that column should be always visible.
2148 \param name - column name
2149 \param appr - new appropriate status
2151 void SUIT_ProxyModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
2154 treeModel()->setAppropriate( name, appr );
2158 \brief Check if the column should appear in the tree view header popup menu
2159 (to show/hide the column).
2161 Default implementation (if appropriate status is not specified yet)
2162 returns \c Shown, it means that column should be always visible.
2164 \param name - column name
2165 \return appropriate status
2167 Qtx::Appropriate SUIT_ProxyModel::appropriate( const QString& name ) const
2169 return treeModel() ? treeModel()->appropriate( name ) : Qtx::Shown;
2173 \brief Set header flags.
2175 These flags allow show in the header of the column text (name of the column),
2176 icon or both text and icon.
2178 \param name - column name
2179 \param flags - header flags
2182 void SUIT_ProxyModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
2185 treeModel()->setHeaderFlags(name, flags);
2189 \brief Get the header flags.
2191 These flags allow show in the header of the column text (name of the column),
2192 icon or both text and icon.
2194 \param name - column name
2195 \return header flags
2197 Qtx::HeaderViewFlags SUIT_ProxyModel::headerFlags( const QString& name ) const
2199 return treeModel() ? treeModel()->headerFlags( name ) : Qtx::ShowAll;
2203 \brief Set visibility state of the object.
2205 \param id - column name
2206 \param state - visible state
2207 \param emitChanged - if set to false, blocks dataChanged() signal, this can be used to
2208 prevent emitting dataChanged() several times for the same data object
2210 void SUIT_ProxyModel::setVisibilityState(const QString& id, Qtx::VisibilityState state, bool emitChanged ) {
2212 treeModel()->setVisibilityState(id,state,emitChanged);
2216 \brief Set visibility state for all objects.
2218 \param id - column name
2219 \param state - visible state
2221 void SUIT_ProxyModel::setVisibilityStateForAll(Qtx::VisibilityState state)
2224 treeModel()->setVisibilityStateForAll(state);
2228 \brief Get visibility state of the object.
2230 \param id - column name
2231 \return visible state
2233 Qtx::VisibilityState SUIT_ProxyModel::visibilityState(const QString& id) const
2235 return treeModel() ? treeModel()->visibilityState(id) : Qtx::UnpresentableState;
2238 void SUIT_ProxyModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index)
2241 treeModel()->emitClicked(obj,index);
2245 \class SUIT_ItemDelegate
2246 \brief An SUIT_DataObject-based item delegate class.
2248 This class can be used to render the SUIT_DataObject-based item
2249 in the widgets like QTreeView and others.
2250 Refer to the Qt 4 documentation, model/view architecture
2251 section for more details).
2256 \param parent parent object
2258 SUIT_ItemDelegate::SUIT_ItemDelegate( QObject* parent )
2259 : QItemDelegate( parent )
2264 \brief Render the item in the widget.
2266 Customizes the item colors for the specific roles.
2268 \param painter painter
2269 \param option painting option
2270 \param index model index being rendered
2272 void SUIT_ItemDelegate::paint( QPainter* painter,
2273 const QStyleOptionViewItem& option,
2274 const QModelIndex& index ) const
2276 QStyleOptionViewItem opt = option;
2277 if ( index.isValid() ) {
2278 // Note: we check into account only custom roles; other roles are process
2279 // correctly by the QItemDelegate class
2280 QVariant val = index.data( SUIT_TreeModel::BaseColorRole );
2281 if ( val.isValid() && val.value<QColor>().isValid() ) {
2282 QColor aBase = val.value<QColor>();
2283 aBase.setAlpha( 0 );
2284 opt.palette.setBrush( QPalette::Base, val.value<QColor>() );
2286 val = index.data( SUIT_TreeModel::TextColorRole );
2287 if ( val.isValid() && val.value<QColor>().isValid() )
2288 opt.palette.setBrush( QPalette::Text, val.value<QColor>() );
2289 val = index.data( SUIT_TreeModel::HighlightRole );
2290 if ( val.isValid() && val.value<QColor>().isValid() )
2291 opt.palette.setBrush( QPalette::Highlight, val.value<QColor>() );
2292 val = index.data( SUIT_TreeModel::HighlightedTextRole );
2293 if ( val.isValid() && val.value<QColor>().isValid() )
2294 opt.palette.setBrush( QPalette::HighlightedText, val.value<QColor>() );
2296 QItemDelegate::paint( painter, opt, index );
2299 QSize SUIT_ItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
2301 QSize size = QItemDelegate::sizeHint ( option, index );
2302 size.setHeight( size.height() + 1 );