1 #include "OB_Browser.h"
4 #include "OB_ListItem.h"
5 #include "OB_ListView.h"
12 #include <qlistview.h>
13 #include <qpopupmenu.h>
16 Class: OB_Browser::ToolTip
17 Descr: Tool tip for OB_Browser.
20 class OB_Browser::ToolTip : public QToolTip
23 ToolTip( OB_Browser* b, QWidget* p = 0 );
26 void maybeTip( const QPoint& );
29 OB_Browser* myBrowser;
32 OB_Browser::ToolTip::ToolTip( OB_Browser* b, QWidget* p )
38 OB_Browser::ToolTip::~ToolTip()
42 void OB_Browser::ToolTip::maybeTip( const QPoint& pos )
44 if ( !parentWidget() || !myBrowser || !myBrowser->isShowToolTips() )
47 QListView* lv = myBrowser->listView();
49 QListViewItem* item = lv->itemAt( pos );
50 SUIT_DataObject* obj = myBrowser->dataObject( item );
54 QString aText = obj->toolTip();
56 if ( aText.isEmpty() )
59 QRect aRect = lv->itemRect( item );
66 Descr: Hierarchical tree object browser.
69 OB_Browser::OB_Browser( QWidget* parent, SUIT_DataObject* root )
75 myAutoUpdate( false ),
76 myAutoDelObjs( false ),
77 myRootDecorated( true )
79 myView = new OB_ListView( QtxListView::HeaderAuto, this );
80 myView->setAppropriate( myView->addColumn( "Data" ), false );
81 myView->setSorting( -1 );
82 myView->setRootIsDecorated( true );
83 myView->setSelectionMode( QListView::Extended );
84 myView->installEventFilter( this );
85 myView->viewport()->installEventFilter( this );
87 QVBoxLayout* main = new QVBoxLayout( this );
88 main->addWidget( myView );
90 myShowToolTips = true;
91 myTooltip = new ToolTip( this, myView->viewport() );
93 connect( myView, SIGNAL( dropped( QPtrList<QListViewItem>, QListViewItem*, int ) ),
94 this, SLOT( onDropped( QPtrList<QListViewItem>, QListViewItem*, int ) ) );
95 connect( myView, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) );
96 connect( myView, SIGNAL( doubleClicked( QListViewItem* ) ),
97 this, SLOT( onDoubleClicked( QListViewItem* ) ) );
99 setRootObject( root );
102 OB_Browser::~OB_Browser()
108 bool OB_Browser::rootIsDecorated() const
110 return myRootDecorated;
113 void OB_Browser::setRootIsDecorated( const bool decor )
115 if ( decor == rootIsDecorated() )
118 myRootDecorated = decor;
122 int OB_Browser::autoOpenLevel() const
124 return myAutoOpenLevel;
127 void OB_Browser::setAutoOpenLevel( const int level )
129 if ( myAutoOpenLevel == level )
132 myAutoOpenLevel = level;
137 bool OB_Browser::isShowToolTips()
139 return myShowToolTips;
142 void OB_Browser::setShowToolTips( const bool theDisplay )
144 myShowToolTips = theDisplay;
147 bool OB_Browser::isAutoUpdate() const
152 void OB_Browser::setAutoUpdate( const bool on )
157 bool OB_Browser::isAutoDeleteObjects() const
159 return myAutoDelObjs;
162 void OB_Browser::setAutoDeleteObjects( const bool on )
167 SUIT_DataObject* OB_Browser::getRootObject() const
172 void OB_Browser::setRootObject( SUIT_DataObject* theRoot )
174 DataObjectKey curKey;
175 DataObjectMap selObjs, openObjs;
176 DataObjectKeyMap selKeys, openKeys;
178 int selNum = numberOfSelected();
180 SUIT_DataObject* curObj = 0;
182 curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
184 removeConnections( myRoot );
185 if ( myRoot != theRoot && isAutoDeleteObjects() )
190 createConnections( myRoot );
193 updateView( myRoot );
194 else if ( listView() )
200 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
204 if ( selNum != numberOfSelected() )
205 emit selectionChanged();
208 int OB_Browser::numberOfSelected() const
213 for ( QListViewItemIterator it( listView() ); it.current(); ++it )
214 if ( it.current()->isSelected() )
220 DataObjectList OB_Browser::getSelected() const
227 void OB_Browser::getSelected( DataObjectList& theObjList ) const
234 for ( QListViewItemIterator it( listView() ); it.current(); ++it )
236 if ( it.current()->isSelected() )
238 SUIT_DataObject* obj = dataObject( it.current() );
240 theObjList.append( obj );
245 void OB_Browser::setSelected( const SUIT_DataObject* theObject, const bool append )
248 lst.append( theObject );
249 setSelected( lst, append );
252 void OB_Browser::setSelected( const DataObjectList& theObjLst, const bool append )
254 QListView* lv = listView();
259 bool changed = false;
260 bool block = lv->signalsBlocked();
261 lv->blockSignals( true );
263 QMap<QListViewItem*, int> map;
264 for ( DataObjectListIterator itr( theObjLst ); itr.current(); ++itr )
265 map.insert( listViewItem( itr.current() ), 0 );
267 for ( QListViewItemIterator it( lv ); it.current(); ++it )
269 QListViewItem* item = it.current();
270 if ( map.contains( item ) && !lv->isSelected( item ) )
273 lv->setSelected( item, true );
275 if ( !append && !map.contains( item ) && lv->isSelected( item ) )
278 lv->setSelected( item, false );
282 lv->blockSignals( block );
287 QListViewItem* sel = 0;
288 QListViewItem* cur = lv->currentItem();
289 for ( QListViewItemIterator iter( lv ); iter.current() && !sel; ++iter, count++ )
291 if ( iter.current()->isSelected() && cur == iter.current() )
292 sel = iter.current();
295 for ( QListViewItemIterator itr( lv ); itr.current() && !sel; ++itr )
297 if ( itr.current()->isSelected() )
302 lv->setCurrentItem( sel );
304 if ( sel && count == 1 )
305 lv->ensureItemVisible( sel );
307 emit selectionChanged();
311 bool OB_Browser::isOpen( SUIT_DataObject* theObject ) const
315 res = listView()->isOpen( listViewItem( theObject ) );
319 void OB_Browser::setOpen( SUIT_DataObject* theObject, const bool theOpen )
322 listView()->setOpen( listViewItem( theObject ), theOpen );
325 SUIT_DataObject* OB_Browser::dataObjectAt( const QPoint& pos ) const
327 SUIT_DataObject* obj = 0;
329 QListView* lv = listView();
331 obj = dataObject( lv->itemAt( pos ) );
336 OB_Filter* OB_Browser::filter() const
338 return myView->filter();
341 void OB_Browser::setFilter( OB_Filter* f )
343 myView->setFilter( f );
346 int OB_Browser::addColumn( const QString& label, const int id, const int width )
348 return addColumn( QIconSet(), label, id, width );
351 int OB_Browser::addColumn( const QIconSet& icon, const QString& label, const int id, const int width )
353 QListView* lv = listView();
360 while ( myColumnIds.contains( theId ) )
364 if ( myColumnIds.contains( theId ) )
365 return -1; // can not reuse id
369 sec = lv->addColumn( label, width );
371 sec = lv->addColumn( icon, label, width );
376 myColumnIds.insert( theId, sec );
382 void OB_Browser::removeColumn( const int id )
384 QListView* lv = listView();
385 if ( !lv || !myColumnIds.contains( id ) )
388 int sec = myColumnIds[id];
389 lv->removeColumn( sec );
391 // update map of column indeces
392 myColumnIds.remove( id );
393 for ( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
401 void OB_Browser::setNameTitle( const QString& label )
403 setNameTitle( QIconSet(), label );
406 void OB_Browser::setNameTitle( const QIconSet& icon, const QString& label )
408 QListView* lv = listView();
413 lv->setColumnText( 0, label );
415 lv->setColumnText( 0, icon, label );
418 void OB_Browser::setColumnTitle( const int id, const QString& label )
420 setColumnTitle( id, QIconSet(), label );
423 void OB_Browser::setColumnTitle( const int id, const QIconSet& icon, const QString& label )
425 QListView* lv = listView();
426 if ( !lv || !myColumnIds.contains( id ) )
430 lv->setColumnText( myColumnIds[id], label );
432 lv->setColumnText( myColumnIds[id], icon, label );
435 QString OB_Browser::nameTitle() const
437 return myView->columnText( 0 );
440 QString OB_Browser::columnTitle( const int id ) const
443 if ( myColumnIds.contains( id ) )
444 txt = myView->columnText( myColumnIds[id] );
448 bool OB_Browser::isColumnVisible( const int id ) const
450 return myColumnIds.contains( id ) && myView->isShown( myColumnIds[id] );
453 void OB_Browser::setColumnShown( const int id, const bool on )
455 if ( !myColumnIds.contains( id ) )
458 myView->setShown( myColumnIds[id], on );
461 void OB_Browser::setWidthMode( QListView::WidthMode mode )
463 for ( int i = 0, n = myView->columns(); i < n; i++ )
464 myView->setColumnWidthMode( i, mode );
467 QValueList<int> OB_Browser::columns() const
470 for ( QMap<int, int>::ConstIterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
471 lst.append( it.key() );
475 bool OB_Browser::appropriateColumn( const int id ) const
478 if ( myColumnIds.contains( id ) )
479 res = myView->appropriate( myColumnIds[id] );
483 void OB_Browser::setAppropriateColumn( const int id, const bool on )
485 if ( !myColumnIds.contains( id ) )
488 myView->setAppropriate( myColumnIds[id], on );
491 void OB_Browser::updateTree( SUIT_DataObject* obj )
493 if ( !obj && !(obj = getRootObject()) )
496 DataObjectKey curKey;
497 DataObjectMap selObjs, openObjs;
498 DataObjectKeyMap selKeys, openKeys;
500 int selNum = numberOfSelected();
502 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
506 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
510 if ( selNum != numberOfSelected() )
511 emit selectionChanged();
514 void OB_Browser::replaceTree( SUIT_DataObject* src, SUIT_DataObject* trg )
516 if ( !src || !trg || src == trg || src->root() != getRootObject() )
519 DataObjectKey curKey;
520 DataObjectMap selObjs, openObjs;
521 DataObjectKeyMap selKeys, openKeys;
523 int selNum = numberOfSelected();
525 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
527 SUIT_DataObject* parent = src->parent();
528 int pos = parent ? parent->childPos( src ) : -1;
532 removeConnections( src );
533 if ( isAutoDeleteObjects() )
536 if ( parent && pos != -1 )
537 parent->insertChild( trg, pos );
539 trg->setParent( parent );
542 createConnections( trg );
544 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
548 if ( selNum != numberOfSelected() )
549 emit selectionChanged();
552 void OB_Browser::updateView( const SUIT_DataObject* theStartObj )
554 QListView* lv = listView();
558 if ( !theStartObj || theStartObj->root() != getRootObject() )
561 QListViewItem* after = 0;
562 QListViewItem* parent = 0;
563 QListViewItem* startItem = listViewItem( theStartObj );
565 if ( theStartObj->parent() )
566 parent = listViewItem( theStartObj->parent() );
568 QListViewItem* prv = 0;
569 QListViewItem* cur = parent ? parent->firstChild() : lv->firstChild();
570 while ( !after && cur )
572 if ( cur == startItem )
576 cur = cur->nextSibling();
579 QPtrList<QListViewItem> delList;
580 if ( !startItem && theStartObj == getRootObject() )
582 for ( QListViewItem* item = lv->firstChild(); item; item = item->nextSibling() )
583 delList.append( item );
586 delList.append( startItem );
588 for ( QPtrListIterator<QListViewItem> it( delList ); it.current(); ++it )
590 removeReferences( it.current() );
594 // for myRoot object, if myShowRoot==false, then creating multiple top-level QListViewItem-s
595 // (which will correspond to myRoot's children = Modules).
596 if ( rootIsDecorated() && theStartObj == myRoot )
599 theStartObj->children( lst );
600 DataObjectListIterator it ( lst );
601 // iterating backward to preserve the order of elements in the tree
602 for ( it.toLast(); it.current(); --it )
603 createTree( it.current(), 0, 0 );
606 createTree( theStartObj, parent, after ? after : parent );
609 QListViewItem* OB_Browser::createTree( const SUIT_DataObject* obj,
610 QListViewItem* parent, QListViewItem* after )
615 QListViewItem* item = createItem( obj, parent, after );
618 obj->children( lst );
619 for ( DataObjectListIterator it ( lst ); it.current(); ++it )
620 createTree( it.current(), item );
623 item->setOpen( obj->isOpen() );
628 QListViewItem* OB_Browser::createItem( const SUIT_DataObject* o,
629 QListViewItem* parent, QListViewItem* after )
631 QListView* lv = listView();
636 QListViewItem* item = 0;
637 SUIT_DataObject* obj = (SUIT_DataObject*)o;
641 switch ( obj->checkType() )
643 case SUIT_DataObject::CheckBox:
644 type = QCheckListItem::CheckBox;
646 case SUIT_DataObject::RadioButton:
647 type = QCheckListItem::RadioButton;
653 if ( parent->childCount() && !after )
655 after = parent->firstChild();
656 while ( after->nextSibling() )
657 after = after->nextSibling();
663 item = new OB_ListItem( obj, parent, after );
665 item = new OB_CheckListItem( obj, parent, after, (QCheckListItem::Type)type );
670 item = new OB_ListItem( obj, parent );
672 item = new OB_CheckListItem( obj, parent, (QCheckListItem::Type)type );
678 item = new OB_ListItem( obj, lv );
680 item = new OB_CheckListItem( obj, lv, (QCheckListItem::Type)type );
683 myItems.insert( obj, item );
684 obj->connect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
691 void OB_Browser::adjustWidth()
696 listView()->setColumnWidth( 0, 0 );
697 if ( listView()->firstChild() )
698 adjustWidth( listView()->firstChild() );
701 void OB_Browser::adjustWidth( QListViewItem* item )
705 item->widthChanged( 0 );
706 if ( item->isOpen() )
707 adjustWidth( item->firstChild() );
708 item = item->nextSibling();
712 SUIT_DataObject* OB_Browser::dataObject( const QListViewItem* item ) const
714 SUIT_DataObject* obj = 0;
716 if ( item && item->rtti() == OB_ListItem::RTTI() )
717 obj = ((OB_ListItem*)item)->dataObject();
718 else if ( item && item->rtti() == OB_CheckListItem::RTTI() )
719 obj = ((OB_CheckListItem*)item)->dataObject();
724 QListViewItem* OB_Browser::listViewItem( const SUIT_DataObject* obj ) const
726 QListViewItem* item = 0;
728 if ( myItems.contains( (SUIT_DataObject*)obj ) )
729 item = myItems[(SUIT_DataObject*)obj];
734 QListView* OB_Browser::listView() const
739 void OB_Browser::removeReferences( QListViewItem* item )
744 SUIT_DataObject* obj = dataObject( item );
745 obj->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
746 myItems.remove( obj );
748 QListViewItem* i = item->firstChild();
751 removeReferences( i );
752 i = i->nextSibling();
756 void OB_Browser::createConnections( SUIT_DataObject* obj )
761 DataObjectList childList;
762 obj->children( childList, true );
764 childList.prepend( obj );
766 for ( DataObjectListIterator it( childList ); it.current(); ++it )
767 it.current()->connect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
770 void OB_Browser::removeConnections( SUIT_DataObject* obj )
775 DataObjectList childList;
776 obj->children( childList, true );
778 childList.prepend( obj );
780 for ( DataObjectListIterator it( childList ); it.current(); ++it )
781 it.current()->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
784 SUIT_DataObject* OB_Browser::storeState( DataObjectMap& selObjs, DataObjectMap& openObjs,
785 DataObjectKeyMap& selKeys, DataObjectKeyMap& openKeys,
786 DataObjectKey& curKey ) const
788 QListView* lv = listView();
792 SUIT_DataObject* curObj = dataObject( lv->currentItem() );
794 curKey = objectKey( curObj );
796 for ( QListViewItemIterator it( lv ); it.current(); ++it )
798 SUIT_DataObject* obj = dataObject( it.current() );
802 selObjs.insert( obj, lv->isSelected( it.current() ) );
803 openObjs.insert( obj, lv->isOpen( it.current() ) );
804 if ( lv->isSelected( it.current() ) )
805 selKeys.insert( objectKey( obj ), 0 );
806 if ( lv->isOpen( it.current() ) )
807 openKeys.insert( objectKey( obj ), 0 );
813 void OB_Browser::restoreState( const DataObjectMap& selObjs, const DataObjectMap& openObjs,
814 const SUIT_DataObject* curObj, const DataObjectKeyMap& selKeys,
815 const DataObjectKeyMap& openKeys, const DataObjectKey& curKey )
817 QListView* lv = listView();
821 bool block = lv->signalsBlocked();
822 lv->blockSignals( true );
824 QListViewItem* curItem = 0;
825 for ( QListViewItemIterator it( lv ); it.current(); ++it )
827 QListViewItem* item = it.current();
828 SUIT_DataObject* obj = dataObject( item );
833 DataObjectKey key = objectKey( obj );
835 if ( selObjs.contains( obj ) )
837 if ( selObjs[obj] && !lv->isSelected( item ) )
838 lv->setSelected( item, true );
840 else if ( !key.isNull() && selKeys.contains( key ) && !lv->isSelected( item ) )
841 lv->setSelected( item, true );
843 if ( openObjs.contains( obj ) )
846 lv->setOpen( item, true );
848 else if ( !key.isNull() && openKeys.contains( key ) )
849 lv->setOpen( item, true );
851 if ( !curItem && ( curObj == obj || ( !curKey.isNull() && curKey == key )) )
856 lv->setCurrentItem( curItem );
858 lv->blockSignals( block );
861 OB_Browser::DataObjectKey OB_Browser::objectKey( QListViewItem* i ) const
863 return objectKey( dataObject( i ) );
866 OB_Browser::DataObjectKey OB_Browser::objectKey( SUIT_DataObject* obj ) const
871 return DataObjectKey( obj->key() );
874 void OB_Browser::keyPressEvent( QKeyEvent* e )
876 if ( e->key() == Qt::Key_F5 )
879 QFrame::keyPressEvent( e );
882 void OB_Browser::onExpand()
884 DataObjectList selected;
885 getSelected( selected );
886 for ( DataObjectListIterator itr( selected ); itr.current(); ++itr )
887 expand( listViewItem( itr.current() ) );
890 void OB_Browser::onColumnVisible( int id )
892 setColumnShown( id, !isColumnVisible( id ) );
895 void OB_Browser::onDestroyed( SUIT_DataObject* obj )
900 void OB_Browser::onDropped( QPtrList<QListViewItem> items, QListViewItem* item, int action )
902 SUIT_DataObject* obj = dataObject( item );
907 for ( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it )
909 SUIT_DataObject* o = dataObject( it.current() );
914 if ( !lst.isEmpty() )
915 emit dropped( lst, obj, action );
918 void OB_Browser::updateText()
920 if ( myColumnIds.isEmpty() )
923 QListView* lv = listView();
927 for ( QListViewItemIterator it( lv ); it.current(); ++it )
929 SUIT_DataObject* obj = dataObject( it.current() );
933 for( QMap<int, int>::iterator itr = myColumnIds.begin(); itr != myColumnIds.end(); ++itr )
934 it.current()->setText( itr.data(), obj->text( itr.key() ) );
938 void OB_Browser::updateText( QListViewItem* item )
940 SUIT_DataObject* obj = dataObject( item );
944 for( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
945 item->setText( it.data(), obj->text( it.key() ) );
948 bool OB_Browser::eventFilter( QObject* o, QEvent* e )
950 if ( o == myView && e->type() == QEvent::ContextMenu )
952 QContextMenuEvent* ce = (QContextMenuEvent*)e;
953 if ( ce->reason() != QContextMenuEvent::Mouse )
954 contextMenuRequest( ce );
957 if ( o == myView->viewport() && e->type() == QEvent::MouseButtonRelease )
959 QMouseEvent* me = (QMouseEvent*)e;
960 if ( me->button() == RightButton )
962 QContextMenuEvent ce( QContextMenuEvent::Mouse, me->pos(), me->globalPos(), me->state() );
963 contextMenuRequest( &ce );
968 return QFrame::eventFilter( o, e );
971 void OB_Browser::contextMenuPopup( QPopupMenu* menu )
973 /* QValueList<int> cols;
974 for ( QMap<int, int>::ConstIterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
976 if ( appropriateColumn( it.key() ) )
977 cols.append( it.key() );
980 uint num = menu->count();
981 menu->setCheckable( true );
982 for ( QValueList<int>::const_iterator iter = cols.begin(); iter != cols.end(); ++iter )
984 QString name = columnTitle( *iter );
985 if ( name.isEmpty() )
988 int id = menu->insertItem( name, this, SLOT( onColumnVisible( int ) ) );
989 menu->setItemChecked( id, isColumnVisible( *iter ) );
990 menu->setItemParameter( id, *iter );
992 if ( menu->count() != num )
993 menu->insertSeparator();*/
995 DataObjectList selected;
996 getSelected( selected );
999 for ( DataObjectListIterator itr( selected ); itr.current() && !closed; ++itr )
1000 closed = hasClosed( listViewItem( itr.current() ) );
1004 menu->insertItem( tr( "MEN_EXPAND_ALL" ), this, SLOT( onExpand() ) );
1005 menu->insertSeparator();
1009 void OB_Browser::expand( QListViewItem* item )
1014 item->setOpen( true );
1015 for ( QListViewItem* child = item->firstChild(); child; child = child->nextSibling() )
1019 bool OB_Browser::hasClosed( QListViewItem* item ) const
1024 if ( item->childCount() && !item->isOpen() )
1028 for ( QListViewItem* child = item->firstChild(); child && !has; child = child->nextSibling() )
1029 has = hasClosed( child );
1034 void OB_Browser::removeObject( SUIT_DataObject* obj, const bool autoUpd )
1039 // Removing list view items from <myItems> recursively for all children.
1040 // Otherwise, "delete item" line will destroy all item's children,
1041 // and <myItems> will contain invalid pointers (see ~QListViewItem() description in Qt docs)
1042 DataObjectList childList;
1043 obj->children( childList );
1044 for ( DataObjectListIterator it( childList ); it.current(); ++it )
1045 removeObject( it.current(), false );
1047 QListViewItem* item = listViewItem( obj );
1049 obj->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
1050 myItems.remove( obj );
1052 if ( obj == myRoot )
1058 if ( isAutoUpdate() )
1060 SUIT_DataObject* pObj = item && item->parent() ? dataObject( item->parent() ) : 0;
1067 void OB_Browser::autoOpenBranches()
1069 int level = autoOpenLevel();
1070 QListView* lv = listView();
1071 if ( !lv || level < 1 )
1074 QListViewItem* item = lv->firstChild();
1077 openBranch( item, level );
1078 item = item->nextSibling();
1082 void OB_Browser::openBranch( QListViewItem* item, const int level )
1089 item->setOpen( true );
1090 openBranch( item->firstChild(), level - 1 );
1091 item = item->nextSibling();
1095 void OB_Browser::onDoubleClicked( QListViewItem* item )
1098 emit doubleClicked( dataObject( item ) );