1 // Copyright (C) 2007-2016 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 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
506 for ( int i=0, n=myColumns.size(); i<n && !found; i++ ) {
507 if ( name == myColumns[i].myName ) {
508 myColumns[i].myIds.insert( group_id, custom_id );
515 inf.myIds.insert( group_id, custom_id );
516 inf.myAppropriate = Qtx::Shown;
517 inf.myHeaderFlags = Qtx::ShowAll;
518 int n = myColumns.size();
519 myColumns.resize( n+1 );
521 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
530 \brief Remove column from the model
532 Please take into account that column is removed only for given group_id, it means
533 that information of data objects with such group_id won't be shown.
534 If there is not any registered group_id for this column after removing, the column will be hidden
535 otherwise it continue to be shown
537 \param group_id - unique data object identificator allowing the classification of objects
538 \param name - translated column name
540 void SUIT_TreeModel::unregisterColumn( const int group_id, const QString& name )
542 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
543 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
546 if ( myColumns[i].myName == name ) {
547 myColumns[i].myIds.remove( group_id );
548 if ( myColumns[i].myIds.isEmpty() ) {
549 myColumns.remove( i );
550 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
562 \brief Change column icon.
564 \param name - column name
565 \param icon - new icon of the specified column
567 void SUIT_TreeModel::setColumnIcon( const QString& name, const QPixmap& icon )
569 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
570 if ( myColumns[i].myName == name ) {
571 myColumns[i].myIcon = icon;
578 \brief Get column icon.
580 \param name - column name
581 \return icon of the specified column
583 QPixmap SUIT_TreeModel::columnIcon( const QString& name ) const
586 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
587 if ( myColumns[i].myName == name ) {
588 res = myColumns[i].myIcon;
596 \brief Change appropriate status
598 Appropriate status determines if the column should appear in the tree view header popup menu
599 (to show/hide the column).
601 If appropriate status is not specified yet, the \c Shown value is taken,
602 it means that column should be always visible.
604 \param name - column name
605 \param appr - new appropriate status
607 void SUIT_TreeModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
609 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
610 if ( myColumns[i].myName == name && myColumns[i].myAppropriate != appr ) {
611 myColumns[i].myAppropriate = appr;
612 emit headerDataChanged( Qt::Horizontal, i, i );
619 \brief Check if the column should appear in the tree view header popup menu
620 (to show/hide the column).
622 Default implementation (if appropriate status is not specified yet)
623 returns \c Shown, it means that column should be always visible.
625 \param name - column name
626 \return appropriate status
628 Qtx::Appropriate SUIT_TreeModel::appropriate( const QString& name ) const
630 Qtx::Appropriate appr = Qtx::Shown;
631 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
632 if ( myColumns[i].myName == name ) {
633 appr = myColumns[i].myAppropriate;
642 \brief Set header flags.
644 These flags allow show in the header of the column text (name of the column),
645 icon or both text and icon.
647 \param name - column name
648 \param flags - header flags
651 void SUIT_TreeModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
653 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
654 if ( myColumns[i].myName == name && myColumns[i].myHeaderFlags != flags ) {
655 myColumns[i].myHeaderFlags = flags;
656 emit headerDataChanged( Qt::Horizontal, i, i );
663 \brief Get the header flags.
665 These flags allow show in the header of the column text (name of the column),
666 icon or both text and icon.
668 \param name - column name
671 Qtx::HeaderViewFlags SUIT_TreeModel::headerFlags( const QString& name ) const
673 Qtx::HeaderViewFlags flags;
674 for ( int i = 0, n = myColumns.size(); i < n; i++ ) {
675 if ( myColumns[i].myName == name ) {
676 flags = myColumns[i].myHeaderFlags;
684 \brief Set visibility state of the object.
686 \param id - column name
687 \param state - visible state
688 \param emitChanged - if set to false, blocks dataChanged() signal, this can be used to
689 prevent emitting dataChanged() several times for the same data object
691 void SUIT_TreeModel::setVisibilityState( const QString& id, Qtx::VisibilityState state, bool emitChanged )
693 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
694 if ( it != myVisibilityMap.end() && it.value() == state )
697 bool needSignal = false;
698 if ( state != Qtx::UnpresentableState ) {
699 myVisibilityMap.insert( id, state );
703 needSignal = myVisibilityMap.remove( id ) > 0;
705 if ( emitChanged && needSignal ) {
708 SUIT_DataObject* o = searcher()->findObject( id );
709 if ( o ) lst << index( o );
712 lst = match( index( 0, root()->customData( Qtx::IdType ).toInt() ), DisplayRole, id, 1, Qt::MatchExactly | Qt::MatchRecursive );
714 if ( !lst.isEmpty() ) {
715 QModelIndex idx = index( lst.first().row(), SUIT_DataObject::VisibilityId, lst.first().parent() );
716 emit dataChanged( idx, idx );
722 \brief Set visibility state for all objects.
724 \param state - visible state
726 void SUIT_TreeModel::setVisibilityStateForAll( Qtx::VisibilityState state )
728 foreach( QString id, myVisibilityMap.keys() )
729 setVisibilityState( id, state );
733 \brief Get visibility state of the object.
735 \param id - column name
736 \return visible state
738 Qtx::VisibilityState SUIT_TreeModel::visibilityState( const QString& id ) const
740 VisibilityMap::const_iterator it = myVisibilityMap.find( id );
741 return it != myVisibilityMap.end() ? it.value() : Qtx::UnpresentableState;
745 \brief Get data tree root object.
746 \return data tree root
749 SUIT_DataObject* SUIT_TreeModel::root() const
755 \brief Set data tree root object.
756 \param r new data tree root
759 void SUIT_TreeModel::setRoot( SUIT_DataObject* r )
764 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
768 if ( autoDeleteTree() ) {
769 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
770 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
771 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
772 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
773 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
774 this, SLOT( onModified( SUIT_DataObject* ) ) );
778 QList<TreeItem*> items = myRootItem->children();
779 for ( QList<TreeItem*>::iterator anIt = items.begin(); anIt != items.end(); anIt++ )
787 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
796 \brief Get data for the specified model index and data role.
797 \param index model index
798 \param role data role
799 \return requested data
802 QVariant SUIT_TreeModel::data( const QModelIndex& index, int role ) const
804 if ( !index.isValid() )
807 SUIT_DataObject* obj = object( index );
814 int obj_group_id = obj->groupId();
815 const ColumnInfo& inf = myColumns[index.column()];
818 if( inf.myIds.contains( 0 ) )
820 if( inf.myIds.contains( obj_group_id ) )
821 id = inf.myIds[obj_group_id];
831 // data object text for the specified column
832 val = obj->text( id );
835 // data object text for the specified column (for editor)
836 val = obj->text( id );
838 case DecorationRole: {
840 if ( id == SUIT_DataObject::VisibilityId ) {
841 // for visibility column, icon is defined specifically (using data object id)
842 QString objId = objectId( index );
843 if ( myVisibilityMap.contains( objId ) ) {
844 // visibility status is defined -> return proper icon
845 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
846 val = ( myVisibilityMap.value( objId ) == Qtx::ShownState ) ?
847 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ) :
848 resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_INVISIBLE" ) );
851 // visibility status is undefined -> no icon
856 // for other columns get icon from the object
857 val = obj->icon( id );
862 // data object tooltip for the specified column
863 val = obj->toolTip( id );
866 // data object status tip for the specified column
867 val = obj->statusTip( id );
870 // data object what's this info for the specified column
871 val = obj->whatsThis( id );
874 // data object font for the specified column
875 val = obj->font( id );
877 case TextAlignmentRole:
878 // data object text alignment for the specified column
879 val = obj->alignment( id );
882 // data background color for the specified column
883 c = obj->color( SUIT_DataObject::Background, id );
884 if( !c.isValid() ) // default value
885 c = QApplication::palette().color( QPalette::Base );
890 // data foreground (text) color for the specified column
891 c = obj->color( SUIT_DataObject::Foreground, id );
892 if( !c.isValid() ) // default value
893 c = QApplication::palette().color( QPalette::Foreground );
897 // editor background color for the specified column
898 c = obj->color( SUIT_DataObject::Base, id );
899 if( !c.isValid() ) // default value
900 c = QApplication::palette().color( QPalette::Base );
904 // editor foreground (text) color for the specified column
905 c = obj->color( SUIT_DataObject::Text, id );
906 if( !c.isValid() ) // default value
907 c = QApplication::palette().color( QPalette::Text );
911 // adta object highlighted background color for the specified column
912 c = obj->color( SUIT_DataObject::Highlight, id );
913 if( !c.isValid() ) // default value
914 c = QApplication::palette().color( QPalette::Highlight );
917 case HighlightedTextRole:
918 // data object highlighted foreground (text) color for the specified column
919 c = obj->color( SUIT_DataObject::HighlightedText, id );
920 if( !c.isValid() ) // default value
921 c = QApplication::palette().color( QPalette::HighlightedText );
925 // data object checked state for the specified column
926 // NOTE! three-state check is not supported currently
927 if( obj->isCheckable( id ) )
928 val = obj->isOn( id ) ? Qt::Checked : Qt::Unchecked;
932 // NOTE! not supported currently
936 } // ... switch ( role ) ...
937 } // ... if ( obj ) ...
942 \brief Set data for the specified model index and data role.
943 \param index model index
944 \param value new data value
945 \param role data role
946 \return \c true if data is set
949 bool SUIT_TreeModel::setData( const QModelIndex& index,
950 const QVariant& value, int role )
952 if ( index.isValid() && value.isValid() ) {
953 SUIT_DataObject* obj = object( index );
955 // NOTE! only 'check state' data is supported by default
959 if ( obj->isCheckable( index.column() ) ) {
960 obj->setOn( value.toBool(), index.column() );
961 emit( dataChanged( index, index ) );
966 QString val = value.toString();
967 bool mod = obj->name() != val;
968 if ( !val.isEmpty() && obj->setName(val) ) {
969 emit( dataChanged( index, index ) );
971 emit ( renamed(obj) );
982 return QAbstractItemModel::setData( index, value, role );
986 \brief Get data flags for specified model index.
987 \param index model index
990 Qt::ItemFlags SUIT_TreeModel::flags( const QModelIndex& index ) const
994 if (!index.isValid())
995 //return Qt::ItemIsDropEnabled; // items can be dropped into the top level of the model
998 SUIT_DataObject* obj = object(index);
1001 // data object is enabled
1002 if (obj->isEnabled())
1003 f = f | Qt::ItemIsEnabled;
1005 // data object is selectable
1006 if (obj->isSelectable())
1007 f = f | Qt::ItemIsSelectable;
1009 // data object is checkable
1010 if (obj->isCheckable(index.column()))
1011 f = f | Qt::ItemIsUserCheckable;
1013 // data object can be renamed
1014 if (obj->renameAllowed(index.column()))
1015 f = f | Qt::ItemIsEditable;
1017 // data object can be dragged
1018 if (obj->isDraggable())
1019 f = f | Qt::ItemIsDragEnabled;
1021 // another data object(s) can be dropped on this one
1022 if (obj->isDropAccepted())
1023 f = f | Qt::ItemIsDropEnabled;
1029 Qt::DropActions SUIT_TreeModel::supportedDropActions() const
1031 return Qt::CopyAction | Qt::MoveAction;
1035 \brief Get header data (can be used in any data view).
1036 \param column column number
1037 \param orientation header orientation
1038 \param role data role
1041 QVariant SUIT_TreeModel::headerData( int column, Qt::Orientation orientation, int role ) const
1044 // NOTE! only horizontal header is supported
1045 if ( root() && orientation == Qt::Horizontal )
1051 if((myColumns[column].myHeaderFlags & Qtx::ShowText) ||
1052 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1053 d = myColumns[column].myName;
1057 case DecorationRole:
1059 if((myColumns[column].myHeaderFlags & Qtx::ShowIcon) ||
1060 (myColumns[column].myHeaderFlags == Qtx::ShowAll))
1061 d = myColumns[column].myIcon;
1065 case AppropriateRole:
1066 // appropriate flag (can column be hidden via context popup menu)
1067 d = myColumns[column].myAppropriate;
1077 \brief Create model index.
1079 \param column data column
1080 \param parent parent model index
1083 QModelIndex SUIT_TreeModel::index( int row, int column,
1084 const QModelIndex& parent ) const
1086 if( hasIndex( row, column, parent ) )
1088 TreeItem* parentItem = treeItem( parent );
1091 TreeItem* childItem = parentItem->child( row );
1093 return createIndex( row, column, childItem );
1096 return QModelIndex();
1100 \brief Get parent model index.
1101 \param index model index
1102 \return parent model index
1104 QModelIndex SUIT_TreeModel::parent( const QModelIndex& index ) const
1106 if ( !index.isValid() )
1107 return QModelIndex();
1109 TreeItem* childItem = treeItem( index );
1110 TreeItem* parentItem = childItem ? childItem->parent() : 0;
1112 if ( !parentItem || parentItem == rootItem() )
1113 return QModelIndex();
1115 return createIndex( parentItem->position(), 0, parentItem );
1119 \brief Get number of data columns.
1120 \param parent parent model index (not used)
1121 \return data columns number
1124 int SUIT_TreeModel::columnCount( const QModelIndex& /*parent*/ ) const
1126 return myColumns.size();
1130 \brief Get number of data rows (children of the specified model index).
1131 \param parent parent model index
1132 \return data rows (children) number
1135 int SUIT_TreeModel::rowCount( const QModelIndex& parent ) const
1137 // Commented by rnv in the frame of the
1138 // "20830: EDF 1357 GUI : Hide/Show Icon" imp
1139 // if ( parent.column() > 0 )
1142 TreeItem* parentItem = treeItem( parent );
1144 return parentItem ? parentItem->childCount() : 0;
1148 \brief Get data object by the specified model index.
1149 \param index model index
1150 \return data object corresponding to the model index
1152 SUIT_DataObject* SUIT_TreeModel::object( const QModelIndex& index ) const
1154 return object( treeItem( index ) );
1158 \brief Get model index by the specified data object.
1159 \param obj data object
1160 \param column data object column
1163 QModelIndex SUIT_TreeModel::index( const SUIT_DataObject* obj, int column ) const
1165 if ( obj == root() )
1166 return QModelIndex();
1168 TreeItem* item = treeItem( obj );
1170 return item ? createIndex( item->position(), column, item ) : QModelIndex();
1174 \brief Get 'auto-delete data tree' flag value.
1175 \return 'auto-delete data tree' flag value
1176 \sa setAutoDeleteTree()
1178 bool SUIT_TreeModel::autoDeleteTree() const
1180 return myAutoDeleteTree;
1184 \brief Set 'auto-delete data tree' flag value.
1186 If this flag is set to \c true, the data tree is deleted when
1187 the tree model is destroyed. Default value for this flag is \c false.
1189 \param on 'auto-delete data tree' flag value
1190 \sa autoDeleteTree()
1192 void SUIT_TreeModel::setAutoDeleteTree( const bool on )
1194 myAutoDeleteTree = on;
1198 \brief Get 'auto-update tree' flag value.
1199 \return 'auto-update tree' flag value
1200 \sa setAutoUpdate(), updateTree()
1202 bool SUIT_TreeModel::autoUpdate() const
1204 return myAutoUpdate;
1208 \brief Set 'auto-update tree' flag value.
1210 If this flag is set to \c true (by default), the model is updated
1211 automatically when data tree is changed.
1213 \param on 'auto-update tree' flag value
1214 \sa autoUpdate(), updateTree()
1216 void SUIT_TreeModel::setAutoUpdate( const bool on )
1218 if ( myAutoUpdate == on )
1221 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1222 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1223 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1224 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1225 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
1226 this, SLOT( onModified( SUIT_DataObject* ) ) );
1229 if ( myAutoUpdate ) {
1230 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1231 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1232 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1233 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1234 SUIT_DataObject::connect( SIGNAL( modified( SUIT_DataObject* ) ),
1235 this, SLOT( onModified( SUIT_DataObject* ) ) );
1242 \brief Get 'updateModified' flag value.
1243 \return 'updateModified' flag value
1245 bool SUIT_TreeModel::updateModified() const
1247 return myUpdateModified;
1250 \brief Set 'updateModified' flag value.
1251 \param on 'updateModified' flag value
1253 void SUIT_TreeModel::setUpdateModified(const bool on)
1255 myUpdateModified=on;
1259 \brief Check if the specified column supports custom sorting.
1260 \param column column index on which data is being sorted
1261 \return \c true if column requires custom sorting
1264 bool SUIT_TreeModel::customSorting( const int column ) const
1266 return root() ? root()->customSorting( column ) : false;
1269 void SUIT_TreeModel::forgetObject( const SUIT_DataObject* obj )
1271 removeItem( treeItem( obj ) );
1275 \brief Compares two model indexes for the sorting purposes.
1277 This method is called only for those columns for which customSorting()
1278 method returns \c true.
1280 \param left first index to compare
1281 \param right second index to compare
1282 \return result of the comparison
1285 bool SUIT_TreeModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
1287 QVariant ldata = data( left );
1288 QVariant rdata = data( right );
1289 return root() ? root()->compare( ldata, rdata, left.column() ) : false;
1293 \brief Get item delegate for the model.
1294 \return new item delegate
1296 QAbstractItemDelegate* SUIT_TreeModel::delegate() const
1298 return new SUIT_ItemDelegate( const_cast<SUIT_TreeModel*>( this ) );
1302 void SUIT_TreeModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index) {
1303 int obj_group_id = obj->groupId();
1304 const ColumnInfo& inf = myColumns[index.column()];
1307 if( inf.myIds.contains( 0 ) )
1309 if( inf.myIds.contains( obj_group_id ) )
1310 id = inf.myIds[obj_group_id];
1311 emit clicked(obj, id);
1315 \brief Update tree model.
1317 Call this method when data tree is changed outside the model.
1318 If the 'auto-update' flag is set to \c true, the model
1319 is updated automatically when the data tree is changed.
1321 \param index starting index for the updating
1324 void SUIT_TreeModel::updateTree( const QModelIndex& index )
1326 updateTree( object( index ) );
1330 void SUIT_TreeModel::updateTreeModel(SUIT_DataObject* obj,TreeItem* item)
1334 int nobjchild=obj->childCount();
1335 SUIT_DataObject* sobj=obj->childObject(kobj);
1336 TreeItem* sitem = item->child(kitem);
1338 while(kobj < nobjchild)
1343 sitem=createItemAtPos(sobj,item,kitem);
1344 updateTreeModel(sobj,sitem);
1347 sobj=obj->childObject(kobj);
1348 sitem = item->child(kitem);
1350 else if(sitem->dataObject() != sobj)
1356 sitem = item->child(kitem);
1361 sitem=createItemAtPos(sobj,item,kitem);
1362 updateTreeModel(sobj,sitem);
1365 sobj=obj->childObject(kobj);
1366 sitem = item->child(kitem);
1371 //obj and item are synchronised : go to next ones
1372 updateTreeModel(sobj,sitem);
1373 if(sobj->modified()) updateItem(sitem, true);
1377 sobj=obj->childObject(kobj);
1378 sitem = item->child(kitem);
1381 //remove remaining items
1382 for(int i = item->childCount(); i > kitem;i--)
1384 sitem = item->child(i-1);
1390 \brief Update tree model.
1392 Call this method when data tree is changed outside the model.
1393 If the 'auto-update' flag is set to \c true, the model
1394 is updated automatically when the data tree is changed.
1396 \param obj starting data object for the updating
1399 void SUIT_TreeModel::updateTree( SUIT_DataObject* obj )
1404 else if ( obj->root() != root() )
1407 if(updateModified())
1409 updateTreeModel(obj,treeItem( obj ));
1413 synchronize<ObjPtr,ItemPtr,SUIT_TreeModel::TreeSync>( obj,
1415 SUIT_TreeModel::TreeSync( this ) );
1417 emit modelUpdated();
1421 \brief Initialize tree model.
1423 void SUIT_TreeModel::initialize()
1425 SUIT_DataObject::disconnect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1426 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1427 SUIT_DataObject::disconnect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1428 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1429 SUIT_DataObject::disconnect( SIGNAL( modified( SUIT_DataObject* ) ),
1430 this, SLOT( onModified( SUIT_DataObject* ) ) );
1431 if ( autoUpdate() ) {
1432 SUIT_DataObject::connect( SIGNAL( inserted( SUIT_DataObject*, SUIT_DataObject* ) ),
1433 this, SLOT( onInserted( SUIT_DataObject*, SUIT_DataObject* ) ) );
1434 SUIT_DataObject::connect( SIGNAL( removed( SUIT_DataObject*, SUIT_DataObject* ) ),
1435 this, SLOT( onRemoved( SUIT_DataObject*, SUIT_DataObject* ) ) );
1436 SUIT_DataObject::connect( SIGNAL( modified( SUIT_DataObject* ) ),
1437 this, SLOT( onModified( SUIT_DataObject* ) ) );
1440 myItems.clear(); // ????? is it really necessary
1443 myRootItem = new TreeItem( 0 );
1445 registerColumn( 0, QObject::tr( "NAME_COLUMN" ), SUIT_DataObject::NameId );
1447 QString visCol = QObject::tr( "VISIBILITY_COLUMN" );
1448 registerColumn( 0, visCol, SUIT_DataObject::VisibilityId );
1450 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1451 setColumnIcon( visCol, resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ));
1452 setHeaderFlags( visCol, Qtx::ShowIcon);
1458 \brief Get root tree item.
1459 \return root tree item
1461 SUIT_TreeModel::TreeItem* SUIT_TreeModel::rootItem() const
1467 \brief Get tree item corresponding to the specified model index.
1468 \param index model index
1469 \return tree item or root item if index is invalid
1471 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const QModelIndex& index ) const
1473 return index.isValid() ? static_cast<TreeItem*>( index.internalPointer() ) : rootItem();
1477 \brief Get tree item corresponding to the specified data object.
1478 \param obj data object
1479 \return tree item or 0 if there is no tree item corresponding to \a obj
1481 SUIT_TreeModel::TreeItem* SUIT_TreeModel::treeItem( const SUIT_DataObject* obj ) const
1485 if ( obj == root() )
1487 else if ( myItems.contains( const_cast<SUIT_DataObject*>( obj ) ) )
1488 item = myItems[ const_cast<SUIT_DataObject*>( obj ) ];
1494 \brief Get data object corresponding to the specified tree item.
1495 \param item tree item
1496 \return data object or 0 if there is no data object corresponding to \a item
1498 SUIT_DataObject* SUIT_TreeModel::object( const SUIT_TreeModel::TreeItem* item ) const
1500 if ( item == rootItem() )
1503 SUIT_DataObject* obj = item ? item->dataObject() : 0;
1504 return myItems.contains( obj ) ? obj : 0;
1508 \brief Get unique object identifier
1510 Object identifier is customized via the Qtx::IdType custom data
1512 \param index model index
1513 \return object identifier or null string if it isn't specified
1514 \sa SUIT_DataObject::customData()
1516 QString SUIT_TreeModel::objectId( const QModelIndex& index ) const
1519 if ( index.isValid() ) {
1520 SUIT_DataObject* obj = object( index );
1522 int anId = obj->customData( Qtx::IdType ).toInt();
1523 objId = data( createIndex( index.row(), anId, index.internalPointer() ) ).toString();
1530 \brief Create an item corresponding to the data object.
1531 \param obj source data object
1532 \param parent parent tree item
1533 \param after tree item after which new item should be inserted
1534 \return created tree item or 0 if item could not be created
1536 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItem( SUIT_DataObject* obj,
1537 SUIT_TreeModel::TreeItem* parent,
1538 SUIT_TreeModel::TreeItem* after )
1543 SUIT_DataObject* parentObj = object( parent );
1544 QModelIndex parentIdx = index( parentObj );
1546 SUIT_DataObject* afterObj = after ? object( after ) : 0;
1547 int row = afterObj ? afterObj->position() + 1 : 0;
1549 beginInsertRows( parentIdx, row, row );
1551 myItems[ obj ] = new TreeItem( obj, parent, after );
1553 for(int pos=row;pos < parent->childCount();pos++)
1554 parent->child(pos)->setPosition(pos);
1558 obj->setModified(false);
1560 return myItems[ obj ];
1564 \brief Create an item corresponding to the data object.
1565 \param obj source data object
1566 \param parent parent tree item
1567 \param pos tree item position into which new item should be inserted
1568 \return created tree item or 0 if item could not be created
1570 SUIT_TreeModel::TreeItem* SUIT_TreeModel::createItemAtPos( SUIT_DataObject* obj,
1571 SUIT_TreeModel::TreeItem* parent,
1577 SUIT_DataObject* parentObj = object( parent );
1578 QModelIndex parentIdx = index( parentObj );
1581 SUIT_TreeModel::TreeItem* after = pos>0 ? parent->child(pos-1) : 0 ;
1583 beginInsertRows( parentIdx, row, row );
1585 SUIT_TreeModel::TreeItem* item = new TreeItem( obj, parent, after );
1586 myItems[ obj ] = item;
1588 for(int ppos=row;ppos < parent->childCount();ppos++)
1589 parent->child(ppos)->setPosition(ppos);
1593 obj->setModified(false);
1599 \brief Update tree item.
1600 \param item tree item to be updated
1601 \param emitLayoutChanged if signal about changed layout should be emitted
1603 void SUIT_TreeModel::updateItem( SUIT_TreeModel::TreeItem* item, bool emitLayoutChanged )
1608 SUIT_DataObject* obj = object( item );
1612 // update all columns corresponding to the given data object
1613 /*To avoid crashes we should update any persistent model indexes before emitting layoutChanged(). In other words, when the structure changes:
1614 - emit layoutAboutToBeChanged
1615 - Remember the QModelIndex that will change
1616 - call changePersistentIndex()
1617 - emit layoutChanged
1620 emit layoutAboutToBeChanged();
1622 // Remember the QModelIndex that will change
1623 QModelIndexList fromIndexes;
1624 QModelIndexList toIndexes;
1625 for (int i = 0; i < columnCount() - 1; ++i) {
1626 fromIndexes.append( index( obj, i ));
1627 toIndexes.append(QModelIndex());
1629 //changePersistentIndexList(fromIndexes, toIndexes); // Limitation: can lead to loss of selection
1631 emit dataChanged( toIndexes.first(), toIndexes.last() );
1632 obj->setModified(false);
1633 if ( emitLayoutChanged )
1634 emit layoutChanged();
1638 \brief Remove tree item (recursively).
1639 \param item tree item to be removed
1641 void SUIT_TreeModel::removeItem( SUIT_TreeModel::TreeItem* item )
1646 // Remove list view items from <myItems> recursively for all children.
1647 // Otherwise, "delete item" line below will destroy all item's children,
1648 // and <myItems> will contain invalid pointers
1649 while( item->childCount() )
1650 removeItem( item->child( 0 ) );
1652 SUIT_DataObject* obj = object( item );
1654 // Warning! obj can be deleted at this point!
1656 TreeItem* parent=item->parent();
1657 SUIT_DataObject* parentObj = object( parent );
1658 QModelIndex parentIdx = index( parentObj, 0 );
1659 int row = item->position();
1661 beginRemoveRows( parentIdx, row, row );
1662 myItems.remove( obj );
1664 if ( obj == root() )
1668 parent->removeChild( item );
1669 for(int pos=row;pos < parent->childCount();pos++)
1670 parent->child(pos)->setPosition(pos);
1679 \brief Called when the data object is inserted to the tree.
1680 \param object data object being inserted
1681 \param parent parent data object
1683 void SUIT_TreeModel::onInserted( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1686 updateTree( parent );
1690 \brief Called when the data object is removed from the tree.
1691 \param object data object being removed
1692 \param parent parent data object
1694 void SUIT_TreeModel::onRemoved( SUIT_DataObject* /*object*/, SUIT_DataObject* parent )
1697 updateTree( parent );
1701 \brief Called when the data object is modified. TreeSync is not used here for maximum efficiency.
1702 It is assumed that it is up to the application to decide when its data objects are modified.
1703 \param obj data object that has been modified
1705 void SUIT_TreeModel::onModified( SUIT_DataObject* obj )
1709 QModelIndex firstIdx = index( obj, 0 );
1710 QModelIndex lastIdx = index( obj, columnCount() - 1 );
1711 emit dataChanged( firstIdx, lastIdx );
1712 obj->setModified(false);
1717 \brief Drag and Drop support.
1719 QStringList SUIT_TreeModel::mimeTypes() const
1722 types << "application/vnd.text.list";
1727 \brief Called when the data objects are exported(dragged) from the tree.
1728 \param indexes the list of exported objects
1730 QMimeData* SUIT_TreeModel::mimeData( const QModelIndexList& indexes ) const
1732 QMimeData* mimeData = new QMimeData();
1733 QByteArray encodedData;
1735 QDataStream stream( &encodedData, QIODevice::WriteOnly );
1737 foreach ( QModelIndex index, indexes ) {
1738 QString id = objectId( index );
1739 // we have to check only 0 column in order to avoid repeating items in the drag object
1740 // - QTreeView tries to drag indices for all visible columns
1741 if ( index.isValid() && index.column() == 0 && !id.isEmpty() )
1745 mimeData->setData( "application/vnd.text.list", encodedData );
1749 bool SUIT_TreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action,
1750 int row, int column, const QModelIndex& parent )
1752 if ( action == Qt::IgnoreAction )
1753 // do nothing with data
1756 if ( !data->hasFormat( "application/vnd.text.list" ) )
1757 // not supported data dropped
1760 if ( !parent.isValid() )
1761 // dropping into the top level of the model is not allowed
1764 // get parent object
1765 SUIT_DataObject* pobj = object( parent );
1770 // decode mime data and collect data objects being dropped
1771 QByteArray encodedData = data->data( "application/vnd.text.list" );
1772 QDataStream stream( &encodedData, QIODevice::ReadOnly );
1774 DataObjectList objects;
1776 while ( !stream.atEnd() ) {
1779 if ( !id.isEmpty() && searcher() ) {
1780 SUIT_DataObject* obj = searcher()->findObject( id );
1781 if ( obj ) objects << obj;
1786 emit dropped( objects, pobj, row, action );
1788 // return true if there's any to drop
1789 return !objects.isEmpty();
1793 \class SUIT_ProxyModel
1794 \brief Proxy model which can be used above the SUIT_TreeModel class
1795 to enable custom sorting/filtering of the data.
1797 The SUIT_TreeModel class does not support custom sorting/filtering of the data.
1798 To use these features, the SUIT_ProxyModel class can be used as top-level
1799 wrapper for the SUIT_DataObject-based data tree model.
1804 \param parent parent object
1806 SUIT_ProxyModel::SUIT_ProxyModel( QObject* parent )
1807 : QSortFilterProxyModel( parent ),
1808 mySortingEnabled( true )
1810 SUIT_TreeModel* model = new SUIT_TreeModel( 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 root root data object
1823 \param parent parent object
1825 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_DataObject* root, QObject* parent )
1826 : QSortFilterProxyModel( parent ),
1827 mySortingEnabled( true )
1829 SUIT_TreeModel* model = new SUIT_TreeModel( root, this );
1830 connect( model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1831 connect( model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1832 connect( model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1833 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1834 connect( model, SIGNAL( renamed( SUIT_DataObject* ) ), this, SIGNAL( renamed( SUIT_DataObject* ) ) );
1835 setSourceModel( model );
1836 setDynamicSortFilter( true );
1841 \param model tree model
1842 \param parent parent object
1844 SUIT_ProxyModel::SUIT_ProxyModel( SUIT_AbstractModel* model, QObject* parent )
1845 : QSortFilterProxyModel( parent ),
1846 mySortingEnabled( true )
1848 connect( *model, SIGNAL( modelUpdated() ), this, SIGNAL( modelUpdated() ) );
1849 connect( *model, SIGNAL( clicked( SUIT_DataObject*, int ) ), this, SIGNAL( clicked( SUIT_DataObject*, int ) ) );
1850 connect( *model, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
1851 this, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
1852 connect( *model, SIGNAL( renamed( SUIT_DataObject* ) ), this, SIGNAL( rename( SUIT_DataObject* ) ) );
1853 setSourceModel( *model );
1854 setDynamicSortFilter( true );
1860 SUIT_ProxyModel::~SUIT_ProxyModel()
1865 \brief Get data tree root object.
1866 \return data tree root
1869 SUIT_DataObject* SUIT_ProxyModel::root() const
1871 return treeModel() ? treeModel()->root() : 0;
1875 \brief Set data tree root object.
1876 \param r new data tree root
1879 void SUIT_ProxyModel::setRoot( SUIT_DataObject* r )
1882 treeModel()->setRoot( r );
1886 \brief Get data object by the specified model index.
1887 \param index model index
1888 \return data object corresponding to the model index
1890 SUIT_DataObject* SUIT_ProxyModel::object( const QModelIndex& index ) const
1892 return treeModel() ? treeModel()->object( mapToSource( index ) ) : 0;
1896 \brief Get model index by the specified data object.
1897 \param obj data object
1898 \param column data object column
1901 QModelIndex SUIT_ProxyModel::index( const SUIT_DataObject* obj, int column ) const
1903 return treeModel() ? mapFromSource( treeModel()->index( obj, column ) ) : QModelIndex();
1907 \brief Get 'auto-delete data tree' flag value.
1908 \return 'auto-delete data tree' flag value
1909 \sa setAutoDeleteTree()
1911 bool SUIT_ProxyModel::autoDeleteTree() const
1913 return treeModel() ? treeModel()->autoDeleteTree() : false;
1917 \brief Set 'auto-delete data tree' flag value.
1919 If this flag is set to \c true, the data tree is deleted when
1920 the tree model is destroyed. Default value for this flag is \c false.
1922 \param on 'auto-delete data tree' flag value
1923 \sa autoDeleteTree()
1925 void SUIT_ProxyModel::setAutoDeleteTree( const bool on )
1928 treeModel()->setAutoDeleteTree( on );
1932 \brief Get 'auto-update tree' flag value.
1933 \return 'auto-update tree' flag value
1934 \sa setAutoUpdate(), updateTree()
1936 bool SUIT_ProxyModel::autoUpdate() const
1938 return treeModel() ? treeModel()->autoUpdate() : false;
1942 \brief Get 'updateModified' flag value.
1943 \return 'updateModified' flag value
1945 bool SUIT_ProxyModel::updateModified() const
1947 return treeModel() ? treeModel()->updateModified() : false;
1950 \brief Set 'updateModified' flag value.
1952 If this flag is set to \c true (default=false), the model is updated by updateTreeModel that
1953 uses the isModified flag to update only modified objects
1955 \param on 'updateModified' flag value
1957 void SUIT_ProxyModel::setUpdateModified( const bool on )
1960 treeModel()->setUpdateModified( on );
1964 \brief Set 'auto-update tree' flag value.
1966 If this flag is set to \c true (by default), the model is updated
1967 automatically when data tree is changed.
1969 \param on 'auto-update tree' flag value
1970 \sa autoUpdate(), updateTree()
1972 void SUIT_ProxyModel::setAutoUpdate( const bool on )
1975 treeModel()->setAutoUpdate( on );
1979 \brief Check if sorting is enabled.
1980 \return \c true if sorting is enabled
1981 \sa setSortingEnabled()
1983 bool SUIT_ProxyModel::isSortingEnabled() const
1985 return mySortingEnabled;
1988 SUIT_DataSearcher* SUIT_ProxyModel::searcher() const
1990 return treeModel() ? treeModel()->searcher() : 0;
1993 void SUIT_ProxyModel::setSearcher( SUIT_DataSearcher* s )
1995 if ( treeModel() ) treeModel()->setSearcher( s );
1999 \brief Get item delegate for the model.
2000 \return new item delegate
2002 QAbstractItemDelegate* SUIT_ProxyModel::delegate() const
2004 return treeModel() ? treeModel()->delegate() : 0;
2008 \brief Update tree model.
2010 Call this method when data tree is changed outside the model.
2011 If the 'auto-update' flag is set to \c true, the model
2012 is updated automatically when the data tree is changed.
2014 \param index starting index for the updating
2017 void SUIT_ProxyModel::updateTree( const QModelIndex& index )
2020 treeModel()->updateTree( mapToSource( index ) );
2024 \brief Update tree model.
2026 Call this method when data tree is changed outside the model.
2027 If the 'auto-update' flag is set to \c true, the model
2028 is updated automatically when the data tree is changed.
2030 \param obj starting data object for the updating
2033 void SUIT_ProxyModel::updateTree( SUIT_DataObject* obj )
2036 treeModel()->updateTree( obj );
2039 void SUIT_ProxyModel::forgetObject( const SUIT_DataObject* obj )
2042 treeModel()->forgetObject( obj );
2046 \brief Compares two model indexes for the sorting purposes.
2047 \param left first index to compare
2048 \param right second index to compare
2049 \return result of the comparison
2051 bool SUIT_ProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
2053 if ( !isSortingEnabled() && left.isValid() && right.isValid() ) {
2054 return left.row() < right.row();
2056 if ( treeModel() && treeModel()->customSorting( left.column() ) ) {
2057 return treeModel()->lessThan( left, right );
2059 return QSortFilterProxyModel::lessThan( left, right );
2063 \brief Check if the specified column supports custom sorting.
2064 \param column column index on which data is being sorted
2065 \return \c true if column requires custom sorting
2068 bool SUIT_ProxyModel::customSorting( const int column ) const
2070 return treeModel() ? treeModel()->customSorting( column ) : false;
2074 \brief Enable/disable sorting.
2075 \param enabled new flag state
2076 \sa isSortingEnabled()
2078 void SUIT_ProxyModel::setSortingEnabled( bool enabled )
2080 mySortingEnabled = enabled;
2085 \brief Get tree model.
2088 SUIT_AbstractModel* SUIT_ProxyModel::treeModel() const
2090 return dynamic_cast<SUIT_AbstractModel*>( sourceModel() );
2095 \param sourceRow row index of the source data model
2096 \param sourceParent parent model index of the source data model
2097 \return \c true if the specified row should be filtered out (i.e. not displayed) or \c false otherwise
2099 bool SUIT_ProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
2101 SUIT_DataObject* o = treeModel()->object( sourceModel()->index( sourceRow, 0, sourceParent ) );
2102 SUIT_DataObject* p = o ? o->parent() : 0;
2103 return ( !p || p->expandable() ) && o && o->isVisible();
2107 \brief Register new column in the model
2108 \param group_id - unique data object identificator allowing the classification of objects
2109 \param name - translated column name
2110 \param custom_id - custom column id that should be passed into method SUIT_DataObject::data()
2112 void SUIT_ProxyModel::registerColumn( const int group_id, const QString& name, const int custom_id )
2115 treeModel()->registerColumn( group_id, name, custom_id );
2119 \brief Remove column from the model
2121 Please take into account that column is removed only for given group_id, it means
2122 that information of data objects with such group_id won't be shown.
2123 If there is not any registered group_id for this column after removing, the column will be hidden
2124 otherwise it continue to be shown
2126 \param group_id - unique data object identificator allowing the classification of objects
2127 \param name - translated column name
2129 void SUIT_ProxyModel::unregisterColumn( const int group_id, const QString& name )
2132 treeModel()->unregisterColumn( group_id, name );
2136 \brief Change column icon.
2138 \param name - column name
2139 \param icon - new icon of the specified column
2141 void SUIT_ProxyModel::setColumnIcon( const QString& name, const QPixmap& icon )
2144 treeModel()->setColumnIcon( name, icon );
2148 \brief Get column icon.
2150 \param name - column name
2151 \return icon of the specified column
2153 QPixmap SUIT_ProxyModel::columnIcon( const QString& name ) const
2155 return treeModel() ? treeModel()->columnIcon( name ) : QPixmap();
2159 \brief Change appropriate status
2161 Appropriate status determines if the column should appear in the tree view header popup menu
2162 (to show/hide the column).
2164 If appropriate status is not specified yet, the \c Shown value is taken,
2165 it means that column should be always visible.
2167 \param name - column name
2168 \param appr - new appropriate status
2170 void SUIT_ProxyModel::setAppropriate( const QString& name, const Qtx::Appropriate appr )
2173 treeModel()->setAppropriate( name, appr );
2177 \brief Check if the column should appear in the tree view header popup menu
2178 (to show/hide the column).
2180 Default implementation (if appropriate status is not specified yet)
2181 returns \c Shown, it means that column should be always visible.
2183 \param name - column name
2184 \return appropriate status
2186 Qtx::Appropriate SUIT_ProxyModel::appropriate( const QString& name ) const
2188 return treeModel() ? treeModel()->appropriate( name ) : Qtx::Shown;
2192 \brief Set header flags.
2194 These flags allow show in the header of the column text (name of the column),
2195 icon or both text and icon.
2197 \param name - column name
2198 \param flags - header flags
2201 void SUIT_ProxyModel::setHeaderFlags( const QString& name, const Qtx::HeaderViewFlags flags )
2204 treeModel()->setHeaderFlags(name, flags);
2208 \brief Get the header flags.
2210 These flags allow show in the header of the column text (name of the column),
2211 icon or both text and icon.
2213 \param name - column name
2214 \return header flags
2216 Qtx::HeaderViewFlags SUIT_ProxyModel::headerFlags( const QString& name ) const
2218 return treeModel() ? treeModel()->headerFlags( name ) : Qtx::ShowAll;
2222 \brief Set visibility state of the object.
2224 \param id - column name
2225 \param state - visible state
2226 \param emitChanged - if set to false, blocks dataChanged() signal, this can be used to
2227 prevent emitting dataChanged() several times for the same data object
2229 void SUIT_ProxyModel::setVisibilityState(const QString& id, Qtx::VisibilityState state, bool emitChanged ) {
2231 treeModel()->setVisibilityState(id,state,emitChanged);
2235 \brief Set visibility state for all objects.
2237 \param id - column name
2238 \param state - visible state
2240 void SUIT_ProxyModel::setVisibilityStateForAll(Qtx::VisibilityState state)
2243 treeModel()->setVisibilityStateForAll(state);
2247 \brief Get visibility state of the object.
2249 \param id - column name
2250 \return visible state
2252 Qtx::VisibilityState SUIT_ProxyModel::visibilityState(const QString& id) const
2254 return treeModel() ? treeModel()->visibilityState(id) : Qtx::UnpresentableState;
2257 void SUIT_ProxyModel::emitClicked( SUIT_DataObject* obj, const QModelIndex& index)
2260 treeModel()->emitClicked(obj,index);
2264 \class SUIT_ItemDelegate
2265 \brief An SUIT_DataObject-based item delegate class.
2267 This class can be used to render the SUIT_DataObject-based item
2268 in the widgets like QTreeView and others.
2269 Refer to the Qt 4 documentation, model/view architecture
2270 section for more details).
2275 \param parent parent object
2277 SUIT_ItemDelegate::SUIT_ItemDelegate( QObject* parent )
2278 : QItemDelegate( parent )
2283 \brief Render the item in the widget.
2285 Customizes the item colors for the specific roles.
2287 \param painter painter
2288 \param option painting option
2289 \param index model index being rendered
2291 void SUIT_ItemDelegate::paint( QPainter* painter,
2292 const QStyleOptionViewItem& option,
2293 const QModelIndex& index ) const
2295 QStyleOptionViewItem opt = option;
2296 if ( index.isValid() ) {
2297 // Note: we check into account only custom roles; other roles are process
2298 // correctly by the QItemDelegate class
2299 QVariant val = index.data( SUIT_TreeModel::BaseColorRole );
2300 if ( val.isValid() && val.value<QColor>().isValid() ) {
2301 QColor aBase = val.value<QColor>();
2302 aBase.setAlpha( 0 );
2303 opt.palette.setBrush( QPalette::Base, val.value<QColor>() );
2305 val = index.data( SUIT_TreeModel::TextColorRole );
2306 if ( val.isValid() && val.value<QColor>().isValid() )
2307 opt.palette.setBrush( QPalette::Text, val.value<QColor>() );
2308 val = index.data( SUIT_TreeModel::HighlightRole );
2309 if ( val.isValid() && val.value<QColor>().isValid() )
2310 opt.palette.setBrush( QPalette::Highlight, val.value<QColor>() );
2311 val = index.data( SUIT_TreeModel::HighlightedTextRole );
2312 if ( val.isValid() && val.value<QColor>().isValid() )
2313 opt.palette.setBrush( QPalette::HighlightedText, val.value<QColor>() );
2315 QItemDelegate::paint( painter, opt, index );
2318 QSize SUIT_ItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
2320 QSize size = QItemDelegate::sizeHint ( option, index );
2321 #if QT_VERSION >= 0x040500
2322 size.setHeight( size.height() + 1 );