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 );
86 QVBoxLayout* main = new QVBoxLayout( this );
87 main->addWidget( myView );
89 myShowToolTips = true;
90 myTooltip = new ToolTip( this, myView->viewport() );
92 connect( myView, SIGNAL( dropped( QPtrList<QListViewItem>, QListViewItem*, int ) ),
93 this, SLOT( onDropped( QPtrList<QListViewItem>, QListViewItem*, int ) ) );
94 connect( myView, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) );
96 setRootObject( root );
99 OB_Browser::~OB_Browser()
105 bool OB_Browser::rootIsDecorated() const
107 return myRootDecorated;
110 void OB_Browser::setRootIsDecorated( const bool decor )
112 if ( decor == rootIsDecorated() )
115 myRootDecorated = decor;
119 int OB_Browser::autoOpenLevel() const
121 return myAutoOpenLevel;
124 void OB_Browser::setAutoOpenLevel( const int level )
126 if ( myAutoOpenLevel == level )
129 myAutoOpenLevel = level;
134 bool OB_Browser::isShowToolTips()
136 return myShowToolTips;
139 void OB_Browser::setShowToolTips( const bool theDisplay )
141 myShowToolTips = theDisplay;
144 bool OB_Browser::isAutoUpdate() const
149 void OB_Browser::setAutoUpdate( const bool on )
154 bool OB_Browser::isAutoDeleteObjects() const
156 return myAutoDelObjs;
159 void OB_Browser::setAutoDeleteObjects( const bool on )
164 SUIT_DataObject* OB_Browser::getRootObject() const
169 void OB_Browser::setRootObject( SUIT_DataObject* theRoot )
171 DataObjectKey curKey;
172 DataObjectMap selObjs, openObjs;
173 DataObjectKeyMap selKeys, openKeys;
175 int selNum = numberOfSelected();
177 SUIT_DataObject* curObj = 0;
179 curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
181 if ( myRoot != theRoot && isAutoDeleteObjects() )
186 createConnections( myRoot );
189 updateView( myRoot );
190 else if ( listView() )
196 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
200 if ( selNum != numberOfSelected() )
201 emit selectionChanged();
204 int OB_Browser::numberOfSelected() const
209 for ( QListViewItemIterator it( listView() ); it.current(); ++it )
210 if ( it.current()->isSelected() )
216 DataObjectList OB_Browser::getSelected() const
223 void OB_Browser::getSelected( DataObjectList& theObjList ) const
230 for ( QListViewItemIterator it( listView() ); it.current(); ++it )
232 if ( it.current()->isSelected() )
234 SUIT_DataObject* obj = dataObject( it.current() );
236 theObjList.append( obj );
241 void OB_Browser::setSelected( const SUIT_DataObject* theObject, const bool append )
244 lst.append( theObject );
245 setSelected( lst, append );
248 void OB_Browser::setSelected( const DataObjectList& theObjLst, const bool append )
250 QListView* lv = listView();
255 bool changed = false;
256 bool block = lv->signalsBlocked();
257 lv->blockSignals( true );
259 QMap<QListViewItem*, int> map;
260 for ( DataObjectListIterator itr( theObjLst ); itr.current(); ++itr )
261 map.insert( listViewItem( itr.current() ), 0 );
263 for ( QListViewItemIterator it( lv ); it.current(); ++it )
265 QListViewItem* item = it.current();
266 if ( map.contains( item ) && !lv->isSelected( item ) )
269 lv->setSelected( item, true );
271 if ( !append && !map.contains( item ) && lv->isSelected( item ) )
274 lv->setSelected( item, false );
278 lv->blockSignals( block );
283 QListViewItem* sel = 0;
284 QListViewItem* cur = lv->currentItem();
285 for ( QListViewItemIterator iter( lv ); iter.current() && !sel; ++iter, count++ )
287 if ( iter.current()->isSelected() && cur == iter.current() )
288 sel = iter.current();
291 for ( QListViewItemIterator itr( lv ); itr.current() && !sel; ++itr )
293 if ( itr.current()->isSelected() )
298 lv->setCurrentItem( sel );
300 if ( sel && count == 1 )
301 lv->ensureItemVisible( sel );
303 emit selectionChanged();
307 bool OB_Browser::isOpen( SUIT_DataObject* theObject ) const
311 res = listView()->isOpen( listViewItem( theObject ) );
315 void OB_Browser::setOpen( SUIT_DataObject* theObject, const bool theOpen )
318 listView()->setOpen( listViewItem( theObject ), theOpen );
321 SUIT_DataObject* OB_Browser::dataObjectAt( const QPoint& pos ) const
323 SUIT_DataObject* obj = 0;
325 QListView* lv = listView();
327 obj = dataObject( lv->itemAt( pos ) );
332 OB_Filter* OB_Browser::filter() const
334 return myView->filter();
337 void OB_Browser::setFilter( OB_Filter* f )
339 myView->setFilter( f );
342 int OB_Browser::addColumn( const QString& label, const int id, const int width )
344 return addColumn( QIconSet(), label, id, width );
347 int OB_Browser::addColumn( const QIconSet& icon, const QString& label, const int id, const int width )
349 QListView* lv = listView();
356 while ( myColumnIds.contains( theId ) )
360 if ( myColumnIds.contains( theId ) )
361 return -1; // can not reuse id
365 sec = lv->addColumn( label, width );
367 sec = lv->addColumn( icon, label, width );
372 myColumnIds.insert( theId, sec );
378 void OB_Browser::removeColumn( const int id )
380 QListView* lv = listView();
381 if ( !lv || !myColumnIds.contains( id ) )
384 int sec = myColumnIds[id];
385 lv->removeColumn( sec );
387 // update map of column indeces
388 myColumnIds.remove( id );
389 for ( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
397 void OB_Browser::setNameTitle( const QString& label )
399 setNameTitle( QIconSet(), label );
402 void OB_Browser::setNameTitle( const QIconSet& icon, const QString& label )
404 QListView* lv = listView();
409 lv->setColumnText( 0, label );
411 lv->setColumnText( 0, icon, label );
414 void OB_Browser::setColumnTitle( const int id, const QString& label )
416 setColumnTitle( id, QIconSet(), label );
419 void OB_Browser::setColumnTitle( const int id, const QIconSet& icon, const QString& label )
421 QListView* lv = listView();
422 if ( !lv || !myColumnIds.contains( id ) )
426 lv->setColumnText( myColumnIds[id], label );
428 lv->setColumnText( myColumnIds[id], icon, label );
431 bool OB_Browser::isColumnVisible( const int id ) const
433 return myColumnIds.contains( id ) && myView->isShown( myColumnIds[id] );
436 void OB_Browser::setColumnShown( const int id, const bool on )
438 if ( !myColumnIds.contains( id ) )
441 myView->setShown( myColumnIds[id], on );
444 QValueList<int> OB_Browser::columns() const
447 for ( QMap<int, int>::ConstIterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
448 lst.append( it.key() );
452 void OB_Browser::updateTree( SUIT_DataObject* o )
454 updateTree( o ? o : getRootObject(), false );
457 void OB_Browser::updateTree( SUIT_DataObject* obj, const bool notify )
462 DataObjectKey curKey;
463 DataObjectMap selObjs, openObjs;
464 DataObjectKeyMap selKeys, openKeys;
466 int selNum = numberOfSelected();
468 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
472 bool upd = isAutoUpdate();
473 setAutoUpdate( false );
475 setAutoUpdate( upd );
478 createConnections( obj );
481 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
485 if ( selNum != numberOfSelected() )
486 emit selectionChanged();
489 void OB_Browser::replaceTree( SUIT_DataObject* src, SUIT_DataObject* trg )
491 if ( !src || !trg || src->root() != getRootObject() )
494 DataObjectKey curKey;
495 DataObjectMap selObjs, openObjs;
496 DataObjectKeyMap selKeys, openKeys;
498 int selNum = numberOfSelected();
500 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
502 SUIT_DataObject* parent = src->parent();
503 int pos = parent ? parent->childPos( src ) : -1;
507 if ( src != trg && isAutoDeleteObjects() )
510 if ( parent && pos != -1 )
511 parent->insertChild( trg, pos );
513 trg->setParent( parent );
515 createConnections( trg );
518 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
522 if ( selNum != numberOfSelected() )
523 emit selectionChanged();
526 void OB_Browser::updateView( const SUIT_DataObject* theStartObj )
528 QListView* lv = listView();
532 if ( !theStartObj || theStartObj->root() != getRootObject() )
535 QListViewItem* after = 0;
536 QListViewItem* parent = 0;
537 QListViewItem* startItem = listViewItem( theStartObj );
539 if ( theStartObj->parent() )
540 parent = listViewItem( theStartObj->parent() );
542 QListViewItem* prv = 0;
543 QListViewItem* cur = parent ? parent->firstChild() : lv->firstChild();
544 while ( !after && cur )
546 if ( cur == startItem )
550 cur = cur->nextSibling();
553 QPtrList<QListViewItem> delList;
554 if ( !startItem && theStartObj == getRootObject() )
556 for ( QListViewItem* item = lv->firstChild(); item; item = item->nextSibling() )
557 delList.append( item );
560 delList.append( startItem );
562 for ( QPtrListIterator<QListViewItem> it( delList ); it.current(); ++it )
564 removeReferences( it.current() );
568 // for myRoot object, if myShowRoot==false, then creating multiple top-level QListViewItem-s
569 // (which will correspond to myRoot's children = Modules).
570 if ( rootIsDecorated() && theStartObj == myRoot )
573 theStartObj->children( lst );
574 DataObjectListIterator it ( lst );
575 // iterating backward to preserve the order of elements in the tree
576 for ( it.toLast(); it.current(); --it )
577 createTree( it.current(), 0, 0 );
580 createTree( theStartObj, parent, after );
583 QListViewItem* OB_Browser::createTree( const SUIT_DataObject* obj,
584 QListViewItem* parent, QListViewItem* after )
589 QListViewItem* item = createItem( obj, parent, after );
592 obj->children( lst );
593 for ( DataObjectListIterator it ( lst ); it.current(); ++it )
594 createTree( it.current(), item );
599 QListViewItem* OB_Browser::createItem( const SUIT_DataObject* o,
600 QListViewItem* parent, QListViewItem* after )
602 QListView* lv = listView();
607 QListViewItem* item = 0;
608 SUIT_DataObject* obj = (SUIT_DataObject*)o;
612 switch ( obj->checkType() )
614 case SUIT_DataObject::CheckBox:
615 type = QCheckListItem::CheckBox;
617 case SUIT_DataObject::RadioButton:
618 type = QCheckListItem::RadioButton;
624 if ( parent->childCount() && !after )
626 after = parent->firstChild();
627 while ( after->nextSibling() )
628 after = after->nextSibling();
634 item = new OB_ListItem( obj, parent, after );
636 item = new OB_CheckListItem( obj, parent, after, (QCheckListItem::Type)type );
641 item = new OB_ListItem( obj, parent );
643 item = new OB_CheckListItem( obj, parent, (QCheckListItem::Type)type );
649 item = new OB_ListItem( obj, lv );
651 item = new OB_CheckListItem( obj, lv, (QCheckListItem::Type)type );
654 myItems.insert( obj, item );
661 void OB_Browser::adjustWidth()
666 listView()->setColumnWidth( 0, 0 );
667 if ( listView()->firstChild() )
668 adjustWidth( listView()->firstChild() );
671 void OB_Browser::adjustWidth( QListViewItem* item )
675 item->widthChanged( 0 );
676 if ( item->isOpen() )
677 adjustWidth( item->firstChild() );
678 item = item->nextSibling();
682 SUIT_DataObject* OB_Browser::dataObject( const QListViewItem* item ) const
684 SUIT_DataObject* obj = 0;
686 if ( item && item->rtti() == OB_ListItem::RTTI() )
687 obj = ((OB_ListItem*)item)->dataObject();
688 else if ( item && item->rtti() == OB_CheckListItem::RTTI() )
689 obj = ((OB_CheckListItem*)item)->dataObject();
694 QListViewItem* OB_Browser::listViewItem( const SUIT_DataObject* obj ) const
696 QListViewItem* item = 0;
698 if ( myItems.contains( (SUIT_DataObject*)obj ) )
699 item = myItems[(SUIT_DataObject*)obj];
704 QListView* OB_Browser::listView() const
709 void OB_Browser::removeReferences( QListViewItem* item )
714 SUIT_DataObject* obj = dataObject( item );
715 myItems.remove( obj );
717 QListViewItem* i = item->firstChild();
720 removeReferences( i );
721 i = i->nextSibling();
725 void OB_Browser::createConnections( SUIT_DataObject* obj )
730 DataObjectList childList;
731 obj->children( childList, true );
733 childList.prepend( obj );
735 for ( DataObjectListIterator it( childList ); it.current(); ++it )
736 it.current()->connect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
739 SUIT_DataObject* OB_Browser::storeState( DataObjectMap& selObjs, DataObjectMap& openObjs,
740 DataObjectKeyMap& selKeys, DataObjectKeyMap& openKeys,
741 DataObjectKey& curKey ) const
743 QListView* lv = listView();
747 SUIT_DataObject* curObj = dataObject( lv->currentItem() );
749 curKey = objectKey( curObj );
751 for ( QListViewItemIterator it( lv ); it.current(); ++it )
753 SUIT_DataObject* obj = dataObject( it.current() );
757 selObjs.insert( obj, lv->isSelected( it.current() ) );
758 openObjs.insert( obj, lv->isOpen( it.current() ) );
759 if ( lv->isSelected( it.current() ) )
760 selKeys.insert( objectKey( obj ), 0 );
761 if ( lv->isOpen( it.current() ) )
762 openKeys.insert( objectKey( obj ), 0 );
768 void OB_Browser::restoreState( const DataObjectMap& selObjs, const DataObjectMap& openObjs,
769 const SUIT_DataObject* curObj, const DataObjectKeyMap& selKeys,
770 const DataObjectKeyMap& openKeys, const DataObjectKey& curKey )
772 QListView* lv = listView();
776 bool block = lv->signalsBlocked();
777 lv->blockSignals( true );
779 QListViewItem* curItem = 0;
780 for ( QListViewItemIterator it( lv ); it.current(); ++it )
782 QListViewItem* item = it.current();
783 SUIT_DataObject* obj = dataObject( item );
788 DataObjectKey key = objectKey( obj );
790 if ( selObjs.contains( obj ) )
792 if ( selObjs[obj] && !lv->isSelected( item ) )
793 lv->setSelected( item, true );
795 else if ( !key.isNull() && selKeys.contains( key ) && !lv->isSelected( item ) )
796 lv->setSelected( item, true );
798 if ( openObjs.contains( obj ) )
801 lv->setOpen( item, true );
803 else if ( !key.isNull() && openKeys.contains( key ) )
804 lv->setOpen( item, true );
806 if ( !curItem && ( curObj == obj || ( !curKey.isNull() && curKey == key )) )
811 lv->setCurrentItem( curItem );
813 lv->blockSignals( block );
816 OB_Browser::DataObjectKey OB_Browser::objectKey( QListViewItem* i ) const
818 return objectKey( dataObject( i ) );
821 OB_Browser::DataObjectKey OB_Browser::objectKey( SUIT_DataObject* obj ) const
826 return DataObjectKey( obj->key() );
829 void OB_Browser::keyPressEvent( QKeyEvent* e )
831 if ( e->key() == Qt::Key_F5 )
834 QFrame::keyPressEvent( e );
837 void OB_Browser::onExpand()
839 DataObjectList selected;
840 getSelected( selected );
841 for ( DataObjectListIterator itr( selected ); itr.current(); ++itr )
842 expand( listViewItem( itr.current() ) );
845 void OB_Browser::onRefresh()
847 updateTree( 0, true );
850 void OB_Browser::onDestroyed( SUIT_DataObject* obj )
855 void OB_Browser::onDropped( QPtrList<QListViewItem> items, QListViewItem* item, int action )
857 SUIT_DataObject* obj = dataObject( item );
862 for ( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it )
864 SUIT_DataObject* o = dataObject( it.current() );
869 if ( !lst.isEmpty() )
870 emit dropped( lst, obj, action );
873 void OB_Browser::updateText()
875 if ( myColumnIds.isEmpty() )
878 QListView* lv = listView();
882 for ( QListViewItemIterator it( lv ); it.current(); ++it )
884 SUIT_DataObject* obj = dataObject( it.current() );
888 for( QMap<int, int>::iterator itr = myColumnIds.begin(); itr != myColumnIds.end(); ++itr )
889 it.current()->setText( itr.data(), obj->text( itr.key() ) );
893 void OB_Browser::updateText( QListViewItem* item )
895 SUIT_DataObject* obj = dataObject( item );
899 for( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
900 item->setText( it.data(), obj->text( it.key() ) );
903 bool OB_Browser::eventFilter( QObject* o, QEvent* e )
905 if ( o == myView && e->type() == QEvent::ContextMenu )
907 QContextMenuEvent* ce = (QContextMenuEvent*)e;
908 if ( ce->reason() != QContextMenuEvent::Mouse )
909 contextMenuRequest( ce );
912 if ( o == myView && e->type() == QEvent::MouseButtonRelease )
914 QMouseEvent* me = (QMouseEvent*)e;
915 if ( me->button() == RightButton )
917 QContextMenuEvent ce( QContextMenuEvent::Mouse, me->pos(), me->globalPos(), me->state() );
918 contextMenuRequest( &ce );
923 return QFrame::eventFilter( o, e );
926 void OB_Browser::contextMenuPopup( QPopupMenu* menu )
928 DataObjectList selected;
929 getSelected( selected );
932 for ( DataObjectListIterator itr( selected ); itr.current() && !closed; ++itr )
933 closed = hasClosed( listViewItem( itr.current() ) );
937 menu->insertItem( tr( "MEN_EXPAND_ALL" ), this, SLOT( onExpand() ) );
938 menu->insertSeparator();
940 menu->insertItem( tr( "MEN_REFRESH" ), this, SLOT( onRefresh() ) );
943 void OB_Browser::expand( QListViewItem* item )
948 item->setOpen( true );
949 for ( QListViewItem* child = item->firstChild(); child; child = child->nextSibling() )
953 bool OB_Browser::hasClosed( QListViewItem* item ) const
958 if ( item->childCount() && !item->isOpen() )
962 for ( QListViewItem* child = item->firstChild(); child && !has; child = child->nextSibling() )
963 has = hasClosed( child );
968 void OB_Browser::removeObject( SUIT_DataObject* obj, const bool autoUpd )
973 // Removing list view items from <myItems> recursively for all children.
974 // Otherwise, "delete item" line will destroy all item's children,
975 // and <myItems> will contain invalid pointers (see ~QListViewItem() description in Qt docs)
976 DataObjectList childList;
977 obj->children( childList );
978 for ( DataObjectListIterator it( childList ); it.current(); ++it )
979 removeObject( it.current(), false );
981 QListViewItem* item = listViewItem( obj );
983 myItems.remove( obj );
991 if ( isAutoUpdate() )
993 SUIT_DataObject* pObj = item && item->parent() ? dataObject( item->parent() ) : 0;
1000 void OB_Browser::autoOpenBranches()
1002 int level = autoOpenLevel();
1003 QListView* lv = listView();
1004 if ( !lv || level < 1 )
1007 QListViewItem* item = lv->firstChild();
1010 openBranch( item, level );
1011 item = item->nextSibling();
1015 void OB_Browser::openBranch( QListViewItem* item, const int level )
1017 if ( !item || level < 1 || !item->childCount() )
1020 item->setOpen( true );
1023 openBranch( item, level - 1 );
1024 item = item->nextSibling();