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() ) );
97 setRootObject( root );
100 OB_Browser::~OB_Browser()
106 bool OB_Browser::rootIsDecorated() const
108 return myRootDecorated;
111 void OB_Browser::setRootIsDecorated( const bool decor )
113 if ( decor == rootIsDecorated() )
116 myRootDecorated = decor;
120 int OB_Browser::autoOpenLevel() const
122 return myAutoOpenLevel;
125 void OB_Browser::setAutoOpenLevel( const int level )
127 if ( myAutoOpenLevel == level )
130 myAutoOpenLevel = level;
135 bool OB_Browser::isShowToolTips()
137 return myShowToolTips;
140 void OB_Browser::setShowToolTips( const bool theDisplay )
142 myShowToolTips = theDisplay;
145 bool OB_Browser::isAutoUpdate() const
150 void OB_Browser::setAutoUpdate( const bool on )
155 bool OB_Browser::isAutoDeleteObjects() const
157 return myAutoDelObjs;
160 void OB_Browser::setAutoDeleteObjects( const bool on )
165 SUIT_DataObject* OB_Browser::getRootObject() const
170 void OB_Browser::setRootObject( SUIT_DataObject* theRoot )
172 DataObjectKey curKey;
173 DataObjectMap selObjs, openObjs;
174 DataObjectKeyMap selKeys, openKeys;
176 int selNum = numberOfSelected();
178 SUIT_DataObject* curObj = 0;
180 curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
182 if ( myRoot != theRoot && isAutoDeleteObjects() )
187 createConnections( myRoot );
190 updateView( myRoot );
191 else if ( listView() )
197 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
201 if ( selNum != numberOfSelected() )
202 emit selectionChanged();
205 int OB_Browser::numberOfSelected() const
210 for ( QListViewItemIterator it( listView() ); it.current(); ++it )
211 if ( it.current()->isSelected() )
217 DataObjectList OB_Browser::getSelected() const
224 void OB_Browser::getSelected( DataObjectList& theObjList ) const
231 for ( QListViewItemIterator it( listView() ); it.current(); ++it )
233 if ( it.current()->isSelected() )
235 SUIT_DataObject* obj = dataObject( it.current() );
237 theObjList.append( obj );
242 void OB_Browser::setSelected( const SUIT_DataObject* theObject, const bool append )
245 lst.append( theObject );
246 setSelected( lst, append );
249 void OB_Browser::setSelected( const DataObjectList& theObjLst, const bool append )
251 QListView* lv = listView();
256 bool changed = false;
257 bool block = lv->signalsBlocked();
258 lv->blockSignals( true );
260 QMap<QListViewItem*, int> map;
261 for ( DataObjectListIterator itr( theObjLst ); itr.current(); ++itr )
262 map.insert( listViewItem( itr.current() ), 0 );
264 for ( QListViewItemIterator it( lv ); it.current(); ++it )
266 QListViewItem* item = it.current();
267 if ( map.contains( item ) && !lv->isSelected( item ) )
270 lv->setSelected( item, true );
272 if ( !append && !map.contains( item ) && lv->isSelected( item ) )
275 lv->setSelected( item, false );
279 lv->blockSignals( block );
284 QListViewItem* sel = 0;
285 QListViewItem* cur = lv->currentItem();
286 for ( QListViewItemIterator iter( lv ); iter.current() && !sel; ++iter, count++ )
288 if ( iter.current()->isSelected() && cur == iter.current() )
289 sel = iter.current();
292 for ( QListViewItemIterator itr( lv ); itr.current() && !sel; ++itr )
294 if ( itr.current()->isSelected() )
299 lv->setCurrentItem( sel );
301 if ( sel && count == 1 )
302 lv->ensureItemVisible( sel );
304 emit selectionChanged();
308 bool OB_Browser::isOpen( SUIT_DataObject* theObject ) const
312 res = listView()->isOpen( listViewItem( theObject ) );
316 void OB_Browser::setOpen( SUIT_DataObject* theObject, const bool theOpen )
319 listView()->setOpen( listViewItem( theObject ), theOpen );
322 SUIT_DataObject* OB_Browser::dataObjectAt( const QPoint& pos ) const
324 SUIT_DataObject* obj = 0;
326 QListView* lv = listView();
328 obj = dataObject( lv->itemAt( pos ) );
333 OB_Filter* OB_Browser::filter() const
335 return myView->filter();
338 void OB_Browser::setFilter( OB_Filter* f )
340 myView->setFilter( f );
343 int OB_Browser::addColumn( const QString& label, const int id, const int width )
345 return addColumn( QIconSet(), label, id, width );
348 int OB_Browser::addColumn( const QIconSet& icon, const QString& label, const int id, const int width )
350 QListView* lv = listView();
357 while ( myColumnIds.contains( theId ) )
361 if ( myColumnIds.contains( theId ) )
362 return -1; // can not reuse id
366 sec = lv->addColumn( label, width );
368 sec = lv->addColumn( icon, label, width );
373 myColumnIds.insert( theId, sec );
379 void OB_Browser::removeColumn( const int id )
381 QListView* lv = listView();
382 if ( !lv || !myColumnIds.contains( id ) )
385 int sec = myColumnIds[id];
386 lv->removeColumn( sec );
388 // update map of column indeces
389 myColumnIds.remove( id );
390 for ( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
398 void OB_Browser::setNameTitle( const QString& label )
400 setNameTitle( QIconSet(), label );
403 void OB_Browser::setNameTitle( const QIconSet& icon, const QString& label )
405 QListView* lv = listView();
410 lv->setColumnText( 0, label );
412 lv->setColumnText( 0, icon, label );
415 void OB_Browser::setColumnTitle( const int id, const QString& label )
417 setColumnTitle( id, QIconSet(), label );
420 void OB_Browser::setColumnTitle( const int id, const QIconSet& icon, const QString& label )
422 QListView* lv = listView();
423 if ( !lv || !myColumnIds.contains( id ) )
427 lv->setColumnText( myColumnIds[id], label );
429 lv->setColumnText( myColumnIds[id], icon, label );
432 QString OB_Browser::nameTitle() const
434 return myView->columnText( 0 );
437 QString OB_Browser::columnTitle( const int id ) const
440 if ( myColumnIds.contains( id ) )
441 txt = myView->columnText( myColumnIds[id] );
445 bool OB_Browser::isColumnVisible( const int id ) const
447 return myColumnIds.contains( id ) && myView->isShown( myColumnIds[id] );
450 void OB_Browser::setColumnShown( const int id, const bool on )
452 if ( !myColumnIds.contains( id ) )
455 myView->setShown( myColumnIds[id], on );
458 QValueList<int> OB_Browser::columns() const
461 for ( QMap<int, int>::ConstIterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
462 lst.append( it.key() );
466 bool OB_Browser::appropriateColumn( const int id ) const
469 if ( myColumnIds.contains( id ) )
470 res = myView->appropriate( myColumnIds[id] );
474 void OB_Browser::setAppropriateColumn( const int id, const bool on )
476 if ( !myColumnIds.contains( id ) )
479 myView->setAppropriate( myColumnIds[id], on );
482 void OB_Browser::updateTree( SUIT_DataObject* o )
484 updateTree( o ? o : getRootObject(), false );
487 void OB_Browser::updateTree( SUIT_DataObject* obj, const bool notify )
492 DataObjectKey curKey;
493 DataObjectMap selObjs, openObjs;
494 DataObjectKeyMap selKeys, openKeys;
496 int selNum = numberOfSelected();
498 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
502 bool upd = isAutoUpdate();
503 setAutoUpdate( false );
505 setAutoUpdate( upd );
508 createConnections( obj );
511 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
515 if ( selNum != numberOfSelected() )
516 emit selectionChanged();
519 void OB_Browser::replaceTree( SUIT_DataObject* src, SUIT_DataObject* trg )
521 if ( !src || !trg || src->root() != getRootObject() )
524 DataObjectKey curKey;
525 DataObjectMap selObjs, openObjs;
526 DataObjectKeyMap selKeys, openKeys;
528 int selNum = numberOfSelected();
530 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
532 SUIT_DataObject* parent = src->parent();
533 int pos = parent ? parent->childPos( src ) : -1;
537 if ( src != trg && isAutoDeleteObjects() )
540 if ( parent && pos != -1 )
541 parent->insertChild( trg, pos );
543 trg->setParent( parent );
545 createConnections( trg );
548 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
552 if ( selNum != numberOfSelected() )
553 emit selectionChanged();
556 void OB_Browser::updateView( const SUIT_DataObject* theStartObj )
558 QListView* lv = listView();
562 if ( !theStartObj || theStartObj->root() != getRootObject() )
565 QListViewItem* after = 0;
566 QListViewItem* parent = 0;
567 QListViewItem* startItem = listViewItem( theStartObj );
569 if ( theStartObj->parent() )
570 parent = listViewItem( theStartObj->parent() );
572 QListViewItem* prv = 0;
573 QListViewItem* cur = parent ? parent->firstChild() : lv->firstChild();
574 while ( !after && cur )
576 if ( cur == startItem )
580 cur = cur->nextSibling();
583 QPtrList<QListViewItem> delList;
584 if ( !startItem && theStartObj == getRootObject() )
586 for ( QListViewItem* item = lv->firstChild(); item; item = item->nextSibling() )
587 delList.append( item );
590 delList.append( startItem );
592 for ( QPtrListIterator<QListViewItem> it( delList ); it.current(); ++it )
594 removeReferences( it.current() );
598 // for myRoot object, if myShowRoot==false, then creating multiple top-level QListViewItem-s
599 // (which will correspond to myRoot's children = Modules).
600 if ( rootIsDecorated() && theStartObj == myRoot )
603 theStartObj->children( lst );
604 DataObjectListIterator it ( lst );
605 // iterating backward to preserve the order of elements in the tree
606 for ( it.toLast(); it.current(); --it )
607 createTree( it.current(), 0, 0 );
610 createTree( theStartObj, parent, after ? after : parent );
613 QListViewItem* OB_Browser::createTree( const SUIT_DataObject* obj,
614 QListViewItem* parent, QListViewItem* after )
619 QListViewItem* item = createItem( obj, parent, after );
622 obj->children( lst );
623 for ( DataObjectListIterator it ( lst ); it.current(); ++it )
624 createTree( it.current(), item );
627 item->setOpen( obj->isOpen() );
632 QListViewItem* OB_Browser::createItem( const SUIT_DataObject* o,
633 QListViewItem* parent, QListViewItem* after )
635 QListView* lv = listView();
640 QListViewItem* item = 0;
641 SUIT_DataObject* obj = (SUIT_DataObject*)o;
645 switch ( obj->checkType() )
647 case SUIT_DataObject::CheckBox:
648 type = QCheckListItem::CheckBox;
650 case SUIT_DataObject::RadioButton:
651 type = QCheckListItem::RadioButton;
657 if ( parent->childCount() && !after )
659 after = parent->firstChild();
660 while ( after->nextSibling() )
661 after = after->nextSibling();
667 item = new OB_ListItem( obj, parent, after );
669 item = new OB_CheckListItem( obj, parent, after, (QCheckListItem::Type)type );
674 item = new OB_ListItem( obj, parent );
676 item = new OB_CheckListItem( obj, parent, (QCheckListItem::Type)type );
682 item = new OB_ListItem( obj, lv );
684 item = new OB_CheckListItem( obj, lv, (QCheckListItem::Type)type );
687 myItems.insert( obj, item );
694 void OB_Browser::adjustWidth()
699 listView()->setColumnWidth( 0, 0 );
700 if ( listView()->firstChild() )
701 adjustWidth( listView()->firstChild() );
704 void OB_Browser::adjustWidth( QListViewItem* item )
708 item->widthChanged( 0 );
709 if ( item->isOpen() )
710 adjustWidth( item->firstChild() );
711 item = item->nextSibling();
715 SUIT_DataObject* OB_Browser::dataObject( const QListViewItem* item ) const
717 SUIT_DataObject* obj = 0;
719 if ( item && item->rtti() == OB_ListItem::RTTI() )
720 obj = ((OB_ListItem*)item)->dataObject();
721 else if ( item && item->rtti() == OB_CheckListItem::RTTI() )
722 obj = ((OB_CheckListItem*)item)->dataObject();
727 QListViewItem* OB_Browser::listViewItem( const SUIT_DataObject* obj ) const
729 QListViewItem* item = 0;
731 if ( myItems.contains( (SUIT_DataObject*)obj ) )
732 item = myItems[(SUIT_DataObject*)obj];
737 QListView* OB_Browser::listView() const
742 void OB_Browser::removeReferences( QListViewItem* item )
747 SUIT_DataObject* obj = dataObject( item );
748 myItems.remove( obj );
750 QListViewItem* i = item->firstChild();
753 removeReferences( i );
754 i = i->nextSibling();
758 void OB_Browser::createConnections( SUIT_DataObject* obj )
763 DataObjectList childList;
764 obj->children( childList, true );
766 childList.prepend( obj );
768 for ( DataObjectListIterator it( childList ); it.current(); ++it )
769 it.current()->connect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
772 SUIT_DataObject* OB_Browser::storeState( DataObjectMap& selObjs, DataObjectMap& openObjs,
773 DataObjectKeyMap& selKeys, DataObjectKeyMap& openKeys,
774 DataObjectKey& curKey ) const
776 QListView* lv = listView();
780 SUIT_DataObject* curObj = dataObject( lv->currentItem() );
782 curKey = objectKey( curObj );
784 for ( QListViewItemIterator it( lv ); it.current(); ++it )
786 SUIT_DataObject* obj = dataObject( it.current() );
790 selObjs.insert( obj, lv->isSelected( it.current() ) );
791 openObjs.insert( obj, lv->isOpen( it.current() ) );
792 if ( lv->isSelected( it.current() ) )
793 selKeys.insert( objectKey( obj ), 0 );
794 if ( lv->isOpen( it.current() ) )
795 openKeys.insert( objectKey( obj ), 0 );
801 void OB_Browser::restoreState( const DataObjectMap& selObjs, const DataObjectMap& openObjs,
802 const SUIT_DataObject* curObj, const DataObjectKeyMap& selKeys,
803 const DataObjectKeyMap& openKeys, const DataObjectKey& curKey )
805 QListView* lv = listView();
809 bool block = lv->signalsBlocked();
810 lv->blockSignals( true );
812 QListViewItem* curItem = 0;
813 for ( QListViewItemIterator it( lv ); it.current(); ++it )
815 QListViewItem* item = it.current();
816 SUIT_DataObject* obj = dataObject( item );
821 DataObjectKey key = objectKey( obj );
823 if ( selObjs.contains( obj ) )
825 if ( selObjs[obj] && !lv->isSelected( item ) )
826 lv->setSelected( item, true );
828 else if ( !key.isNull() && selKeys.contains( key ) && !lv->isSelected( item ) )
829 lv->setSelected( item, true );
831 if ( openObjs.contains( obj ) )
834 lv->setOpen( item, true );
836 else if ( !key.isNull() && openKeys.contains( key ) )
837 lv->setOpen( item, true );
839 if ( !curItem && ( curObj == obj || ( !curKey.isNull() && curKey == key )) )
844 lv->setCurrentItem( curItem );
846 lv->blockSignals( block );
849 OB_Browser::DataObjectKey OB_Browser::objectKey( QListViewItem* i ) const
851 return objectKey( dataObject( i ) );
854 OB_Browser::DataObjectKey OB_Browser::objectKey( SUIT_DataObject* obj ) const
859 return DataObjectKey( obj->key() );
862 void OB_Browser::keyPressEvent( QKeyEvent* e )
864 if ( e->key() == Qt::Key_F5 )
867 QFrame::keyPressEvent( e );
870 void OB_Browser::onExpand()
872 DataObjectList selected;
873 getSelected( selected );
874 for ( DataObjectListIterator itr( selected ); itr.current(); ++itr )
875 expand( listViewItem( itr.current() ) );
878 void OB_Browser::onRefresh()
880 updateTree( getRootObject(), true );
883 void OB_Browser::onColumnVisible( int id )
885 setColumnShown( id, !isColumnVisible( id ) );
888 void OB_Browser::onDestroyed( SUIT_DataObject* obj )
893 void OB_Browser::onDropped( QPtrList<QListViewItem> items, QListViewItem* item, int action )
895 SUIT_DataObject* obj = dataObject( item );
900 for ( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it )
902 SUIT_DataObject* o = dataObject( it.current() );
907 if ( !lst.isEmpty() )
908 emit dropped( lst, obj, action );
911 void OB_Browser::updateText()
913 if ( myColumnIds.isEmpty() )
916 QListView* lv = listView();
920 for ( QListViewItemIterator it( lv ); it.current(); ++it )
922 SUIT_DataObject* obj = dataObject( it.current() );
926 for( QMap<int, int>::iterator itr = myColumnIds.begin(); itr != myColumnIds.end(); ++itr )
927 it.current()->setText( itr.data(), obj->text( itr.key() ) );
931 void OB_Browser::updateText( QListViewItem* item )
933 SUIT_DataObject* obj = dataObject( item );
937 for( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
938 item->setText( it.data(), obj->text( it.key() ) );
941 bool OB_Browser::eventFilter( QObject* o, QEvent* e )
943 if ( o == myView && e->type() == QEvent::ContextMenu )
945 QContextMenuEvent* ce = (QContextMenuEvent*)e;
946 if ( ce->reason() != QContextMenuEvent::Mouse )
947 contextMenuRequest( ce );
950 if ( o == myView->viewport() && e->type() == QEvent::MouseButtonRelease )
952 QMouseEvent* me = (QMouseEvent*)e;
953 if ( me->button() == RightButton )
955 QContextMenuEvent ce( QContextMenuEvent::Mouse, me->pos(), me->globalPos(), me->state() );
956 contextMenuRequest( &ce );
961 return QFrame::eventFilter( o, e );
964 void OB_Browser::contextMenuPopup( QPopupMenu* menu )
966 /* QValueList<int> cols;
967 for ( QMap<int, int>::ConstIterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
969 if ( appropriateColumn( it.key() ) )
970 cols.append( it.key() );
973 uint num = menu->count();
974 menu->setCheckable( true );
975 for ( QValueList<int>::const_iterator iter = cols.begin(); iter != cols.end(); ++iter )
977 QString name = columnTitle( *iter );
978 if ( name.isEmpty() )
981 int id = menu->insertItem( name, this, SLOT( onColumnVisible( int ) ) );
982 menu->setItemChecked( id, isColumnVisible( *iter ) );
983 menu->setItemParameter( id, *iter );
985 if ( menu->count() != num )
986 menu->insertSeparator();*/
988 DataObjectList selected;
989 getSelected( selected );
992 for ( DataObjectListIterator itr( selected ); itr.current() && !closed; ++itr )
993 closed = hasClosed( listViewItem( itr.current() ) );
997 menu->insertItem( tr( "MEN_EXPAND_ALL" ), this, SLOT( onExpand() ) );
998 menu->insertSeparator();
1000 menu->insertItem( tr( "MEN_REFRESH" ), this, SLOT( onRefresh() ) );
1003 void OB_Browser::expand( QListViewItem* item )
1008 item->setOpen( true );
1009 for ( QListViewItem* child = item->firstChild(); child; child = child->nextSibling() )
1013 bool OB_Browser::hasClosed( QListViewItem* item ) const
1018 if ( item->childCount() && !item->isOpen() )
1022 for ( QListViewItem* child = item->firstChild(); child && !has; child = child->nextSibling() )
1023 has = hasClosed( child );
1028 void OB_Browser::removeObject( SUIT_DataObject* obj, const bool autoUpd )
1033 // Removing list view items from <myItems> recursively for all children.
1034 // Otherwise, "delete item" line will destroy all item's children,
1035 // and <myItems> will contain invalid pointers (see ~QListViewItem() description in Qt docs)
1036 DataObjectList childList;
1037 obj->children( childList );
1038 for ( DataObjectListIterator it( childList ); it.current(); ++it )
1039 removeObject( it.current(), false );
1041 QListViewItem* item = listViewItem( obj );
1043 myItems.remove( obj );
1045 if ( obj == myRoot )
1051 if ( isAutoUpdate() )
1053 SUIT_DataObject* pObj = item && item->parent() ? dataObject( item->parent() ) : 0;
1060 void OB_Browser::autoOpenBranches()
1062 int level = autoOpenLevel();
1063 QListView* lv = listView();
1064 if ( !lv || level < 1 )
1067 QListViewItem* item = lv->firstChild();
1070 openBranch( item, level );
1071 item = item->nextSibling();
1075 void OB_Browser::openBranch( QListViewItem* item, const int level )
1077 if ( !item || level < 1 || !item->childCount() )
1080 item->setOpen( true );
1083 openBranch( item->firstChild(), level - 1 );
1084 item = item->nextSibling();