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->getListView();
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 )
74 myAutoUpdate( false ),
75 myAutoDelObjs( false ),
76 myRootDecorated( true )
78 myView = new OB_ListView( this );
79 myView->addColumn( "Data" );
80 myView->setSorting( -1 );
81 myView->setRootIsDecorated( true );
82 myView->setSelectionMode( QListView::Extended );
83 myView->installEventFilter( this );
85 QVBoxLayout* main = new QVBoxLayout( this );
86 main->addWidget( myView );
88 myShowToolTips = true;
89 myTooltip = new ToolTip( this, myView->viewport() );
91 connect( myView, SIGNAL( dropped( QPtrList<QListViewItem>, QListViewItem*, int ) ),
92 this, SLOT( onDropped( QPtrList<QListViewItem>, QListViewItem*, int ) ) );
93 connect( myView, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) );
95 setRootObject( root );
98 OB_Browser::~OB_Browser()
104 bool OB_Browser::rootIsDecorated() const
106 return myRootDecorated;
109 void OB_Browser::setRootIsDecorated( const bool decor )
111 if ( decor == rootIsDecorated() )
114 myRootDecorated = decor;
118 bool OB_Browser::isShowToolTips()
120 return myShowToolTips;
123 void OB_Browser::setShowToolTips( const bool theDisplay )
125 myShowToolTips = theDisplay;
128 bool OB_Browser::isAutoUpdate() const
133 void OB_Browser::setAutoUpdate( const bool on )
138 bool OB_Browser::isAutoDeleteObjects() const
140 return myAutoDelObjs;
143 void OB_Browser::setAutoDeleteObjects( const bool on )
148 SUIT_DataObject* OB_Browser::getRootObject() const
153 void OB_Browser::setRootObject( SUIT_DataObject* theRoot )
155 DataObjectKey curKey;
156 DataObjectMap selObjs, openObjs;
157 DataObjectKeyMap selKeys, openKeys;
159 int selNum = numberOfSelected();
161 SUIT_DataObject* curObj = 0;
163 curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
165 if ( myRoot != theRoot && isAutoDeleteObjects() )
170 createConnections( myRoot );
173 updateView( myRoot );
174 else if ( getListView() )
177 getListView()->clear();
180 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
182 if ( selNum != numberOfSelected() )
183 emit selectionChanged();
186 int OB_Browser::numberOfSelected() const
191 for ( QListViewItemIterator it( getListView() ); it.current(); ++it )
192 if ( it.current()->isSelected() )
198 DataObjectList OB_Browser::getSelected() const
205 void OB_Browser::getSelected( DataObjectList& theObjList ) const
209 if ( !getListView() )
212 for ( QListViewItemIterator it( getListView() ); it.current(); ++it )
214 if ( it.current()->isSelected() )
216 SUIT_DataObject* obj = dataObject( it.current() );
218 theObjList.append( obj );
223 void OB_Browser::setSelected( const SUIT_DataObject* theObject, const bool append )
226 lst.append( theObject );
227 setSelected( lst, append );
230 void OB_Browser::setSelected( const DataObjectList& theObjLst, const bool append )
232 QListView* lv = getListView();
237 bool changed = false;
238 bool block = lv->signalsBlocked();
239 lv->blockSignals( true );
241 QMap<QListViewItem*, int> map;
242 for ( DataObjectListIterator itr( theObjLst ); itr.current(); ++itr )
243 map.insert( listViewItem( itr.current() ), 0 );
245 for ( QListViewItemIterator it( lv ); it.current(); ++it )
247 QListViewItem* item = it.current();
248 if ( map.contains( item ) && !lv->isSelected( item ) )
251 lv->setSelected( item, true );
253 if ( !append && !map.contains( item ) && lv->isSelected( item ) )
256 lv->setSelected( item, false );
260 lv->blockSignals( block );
265 QListViewItem* sel = 0;
266 QListViewItem* cur = lv->currentItem();
267 for ( QListViewItemIterator iter( lv ); iter.current() && !sel; ++iter, count++ )
269 if ( iter.current()->isSelected() && cur == iter.current() )
270 sel = iter.current();
273 for ( QListViewItemIterator itr( lv ); itr.current() && !sel; ++itr )
275 if ( itr.current()->isSelected() )
280 lv->setCurrentItem( sel );
282 if ( sel && count == 1 )
283 lv->ensureItemVisible( sel );
285 emit selectionChanged();
289 bool OB_Browser::isOpen( SUIT_DataObject* theObject ) const
293 res = getListView()->isOpen( listViewItem( theObject ) );
297 void OB_Browser::setOpen( SUIT_DataObject* theObject, const bool theOpen )
300 getListView()->setOpen( listViewItem( theObject ), theOpen );
303 SUIT_DataObject* OB_Browser::dataObjectAt( const QPoint& pos ) const
305 SUIT_DataObject* obj = 0;
307 QListView* lv = getListView();
309 obj = dataObject( lv->itemAt( pos ) );
314 OB_Filter* OB_Browser::filter() const
316 return myView->filter();
319 void OB_Browser::setFilter( OB_Filter* f )
321 myView->setFilter( f );
324 int OB_Browser::addColumn( const QString & label, int width, int index )
329 if ( index != -1 && myColumnIds.contains( index ) )
330 return id; // can not reuse index
333 id = myView->addColumn( label, width );
336 myColumnIds.insert( trueId, id );
342 int OB_Browser::addColumn( const QIconSet & iconset, const QString & label, int width, int index )
347 if ( index != -1 && myColumnIds.contains( index ) )
348 return id; // can not reuse index
351 id = myView->addColumn( iconset, label, width );
354 myColumnIds.insert( trueId, id );
360 void OB_Browser::removeColumn( int index )
362 if ( !myView || !myColumnIds.contains( index ) )
365 int id = myColumnIds[ index ];
366 myView->removeColumn( id );
368 // update map of column indeces
369 myColumnIds.remove( index );
370 for ( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
372 if ( it.key() > index )
378 void OB_Browser::updateTree( SUIT_DataObject* o )
380 SUIT_DataObject* obj = o ? o : getRootObject();
384 DataObjectKey curKey;
385 DataObjectMap selObjs, openObjs;
386 DataObjectKeyMap selKeys, openKeys;
388 int selNum = numberOfSelected();
390 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
392 createConnections( obj );
395 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
397 if ( selNum != numberOfSelected() )
398 emit selectionChanged();
401 void OB_Browser::replaceTree( SUIT_DataObject* src, SUIT_DataObject* trg )
403 if ( !src || !trg || src->root() != getRootObject() )
406 DataObjectKey curKey;
407 DataObjectMap selObjs, openObjs;
408 DataObjectKeyMap selKeys, openKeys;
410 int selNum = numberOfSelected();
412 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
414 SUIT_DataObject* parent = src->parent();
415 int pos = parent ? parent->childPos( src ) : -1;
419 if ( src != trg && isAutoDeleteObjects() )
422 if ( parent && pos != -1 )
423 parent->insertChild( trg, pos );
425 trg->setParent( parent );
427 createConnections( trg );
430 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
432 if ( selNum != numberOfSelected() )
433 emit selectionChanged();
436 void OB_Browser::updateView( const SUIT_DataObject* theStartObj )
438 QListView* lv = getListView();
442 if ( !theStartObj || theStartObj->root() != getRootObject() )
445 QListViewItem* after = 0;
446 QListViewItem* parent = 0;
447 QListViewItem* startItem = listViewItem( theStartObj );
449 if ( theStartObj->parent() )
450 parent = listViewItem( theStartObj->parent() );
452 QListViewItem* prv = 0;
453 QListViewItem* cur = parent ? parent->firstChild() : lv->firstChild();
454 while ( !after && cur )
456 if ( cur == startItem )
460 cur = cur->nextSibling();
463 QPtrList<QListViewItem> delList;
464 if ( !startItem && theStartObj == getRootObject() )
466 for ( QListViewItem* item = lv->firstChild(); item; item = item->nextSibling() )
467 delList.append( item );
470 delList.append( startItem );
472 for ( QPtrListIterator<QListViewItem> it( delList ); it.current(); ++it )
474 removeReferences( it.current() );
478 // for myRoot object, if myShowRoot==false, then creating multiple top-level QListViewItem-s
479 // (which will correspond to myRoot's children = Modules).
480 if ( rootIsDecorated() && theStartObj == myRoot )
483 theStartObj->children( lst );
484 DataObjectListIterator it ( lst );
485 // iterating backward to preserve the order of elements in the tree
486 for ( it.toLast(); it.current(); --it )
487 createTree( it.current(), 0, 0 );
490 createTree( theStartObj, parent, after );
493 QListViewItem* OB_Browser::createTree( const SUIT_DataObject* obj,
494 QListViewItem* parent, QListViewItem* after )
499 QListViewItem* item = createItem( obj, parent, after );
502 obj->children( lst );
503 for ( DataObjectListIterator it ( lst ); it.current(); ++it )
504 createTree( it.current(), item );
509 QListViewItem* OB_Browser::createItem( const SUIT_DataObject* o,
510 QListViewItem* parent, QListViewItem* after )
512 QListView* lv = getListView();
517 QListViewItem* item = 0;
518 SUIT_DataObject* obj = (SUIT_DataObject*)o;
522 switch ( obj->checkType() )
524 case SUIT_DataObject::CheckBox:
525 type = QCheckListItem::CheckBox;
527 case SUIT_DataObject::RadioButton:
528 type = QCheckListItem::RadioButton;
534 if ( parent->childCount() && !after )
536 after = parent->firstChild();
537 while ( after->nextSibling() )
538 after = after->nextSibling();
544 item = new OB_ListItem( obj, parent, after );
546 item = new OB_CheckListItem( obj, parent, after, (QCheckListItem::Type)type );
551 item = new OB_ListItem( obj, parent );
553 item = new OB_CheckListItem( obj, parent, (QCheckListItem::Type)type );
559 item = new OB_ListItem( obj, lv );
561 item = new OB_CheckListItem( obj, lv, (QCheckListItem::Type)type );
564 myItems.insert( obj, item );
569 void OB_Browser::adjustWidth()
571 if ( !getListView() )
574 getListView()->setColumnWidth( 0, 0 );
575 if ( getListView()->firstChild() )
576 adjustWidth( getListView()->firstChild() );
579 void OB_Browser::adjustWidth( QListViewItem* item )
583 item->widthChanged( 0 );
584 if ( item->isOpen() )
585 adjustWidth( item->firstChild() );
586 item = item->nextSibling();
590 SUIT_DataObject* OB_Browser::dataObject( const QListViewItem* item ) const
592 SUIT_DataObject* obj = 0;
594 if ( item && item->rtti() == OB_ListItem::RTTI() )
595 obj = ((OB_ListItem*)item)->dataObject();
596 else if ( item && item->rtti() == OB_CheckListItem::RTTI() )
597 obj = ((OB_CheckListItem*)item)->dataObject();
602 QListViewItem* OB_Browser::listViewItem( const SUIT_DataObject* obj ) const
604 QListViewItem* item = 0;
606 if ( myItems.contains( (SUIT_DataObject*)obj ) )
607 item = myItems[(SUIT_DataObject*)obj];
612 QListView* OB_Browser::getListView() const
617 void OB_Browser::removeReferences( QListViewItem* item )
622 SUIT_DataObject* obj = dataObject( item );
623 myItems.remove( obj );
625 QListViewItem* i = item->firstChild();
628 removeReferences( i );
629 i = i->nextSibling();
633 void OB_Browser::createConnections( SUIT_DataObject* obj )
638 DataObjectList childList;
639 obj->children( childList, true );
641 childList.prepend( obj );
643 for ( DataObjectListIterator it( childList ); it.current(); ++it )
644 it.current()->connect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
647 SUIT_DataObject* OB_Browser::storeState( DataObjectMap& selObjs, DataObjectMap& openObjs,
648 DataObjectKeyMap& selKeys, DataObjectKeyMap& openKeys,
649 DataObjectKey& curKey ) const
651 QListView* lv = getListView();
655 SUIT_DataObject* curObj = dataObject( lv->currentItem() );
657 curKey = objectKey( curObj );
659 for ( QListViewItemIterator it( lv ); it.current(); ++it )
661 SUIT_DataObject* obj = dataObject( it.current() );
665 selObjs.insert( obj, lv->isSelected( it.current() ) );
666 openObjs.insert( obj, lv->isOpen( it.current() ) );
667 if ( lv->isSelected( it.current() ) )
668 selKeys.insert( objectKey( obj ), 0 );
669 if ( lv->isOpen( it.current() ) )
670 openKeys.insert( objectKey( obj ), 0 );
676 void OB_Browser::restoreState( const DataObjectMap& selObjs, const DataObjectMap& openObjs,
677 const SUIT_DataObject* curObj, const DataObjectKeyMap& selKeys,
678 const DataObjectKeyMap& openKeys, const DataObjectKey& curKey )
680 QListView* lv = getListView();
684 bool block = lv->signalsBlocked();
685 lv->blockSignals( true );
687 QListViewItem* curItem = 0;
688 for ( QListViewItemIterator it( lv ); it.current(); ++it )
690 QListViewItem* item = it.current();
691 SUIT_DataObject* obj = dataObject( item );
696 DataObjectKey key = objectKey( obj );
698 if ( selObjs.contains( obj ) )
700 if ( selObjs[obj] && !lv->isSelected( item ) )
701 lv->setSelected( item, true );
703 else if ( !key.isNull() && selKeys.contains( key ) && !lv->isSelected( item ) )
704 lv->setSelected( item, true );
706 if ( openObjs.contains( obj ) )
709 lv->setOpen( item, true );
711 else if ( !key.isNull() && openKeys.contains( key ) )
712 lv->setOpen( item, true );
714 if ( !curItem && ( curObj == obj || ( !curKey.isNull() && curKey == key )) )
719 lv->setCurrentItem( curItem );
721 lv->blockSignals( block );
724 OB_Browser::DataObjectKey OB_Browser::objectKey( QListViewItem* i ) const
726 return objectKey( dataObject( i ) );
729 OB_Browser::DataObjectKey OB_Browser::objectKey( SUIT_DataObject* obj ) const
734 return DataObjectKey( obj->key() );
737 void OB_Browser::keyPressEvent( QKeyEvent* e )
739 if ( e->key() == Qt::Key_F5 )
742 if ( ( e->key() == Qt::Key_Plus || e->key() == Qt::Key_Minus ) &&
743 e->state() & ControlButton && getListView() )
745 bool isOpen = e->key() == Qt::Key_Plus;
746 for ( QListViewItemIterator it( getListView() ); it.current(); ++it )
747 if ( it.current()->childCount() )
748 it.current()->setOpen( isOpen );
751 QFrame::keyPressEvent( e );
754 void OB_Browser::onExpand()
756 DataObjectList selected;
757 getSelected( selected );
758 for ( DataObjectListIterator itr( selected ); itr.current(); ++itr )
759 expand( listViewItem( itr.current() ) );
762 void OB_Browser::onDestroyed( SUIT_DataObject* obj )
767 // Removing list view items from <myItems> recursively for all children.
768 // Otherwise, "delete item" line will destroy all item's children,
769 // and <myItems> will contain invalid pointers (see ~QListViewItem() description in Qt docs)
770 DataObjectList childList;
771 obj->children( childList );
772 for ( DataObjectListIterator it( childList ); it.current(); ++it )
773 onDestroyed( it.current() );
775 QListViewItem* item = listViewItem( obj );
777 myItems.remove( obj );
782 if ( isAutoUpdate() )
784 SUIT_DataObject* pObj = item && item->parent() ? dataObject( item->parent() ) : 0;
791 void OB_Browser::onDropped( QPtrList<QListViewItem> items, QListViewItem* item, int action )
793 SUIT_DataObject* obj = dataObject( item );
798 for ( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it )
800 SUIT_DataObject* o = dataObject( it.current() );
805 if ( !lst.isEmpty() )
806 emit dropped( lst, obj, action );
809 void OB_Browser::updateText()
814 if ( myColumnIds.size() )
816 QListViewItemIterator it( myView );
817 for ( ; it.current() != 0; ++it )
819 QListViewItem* item = it.current();
820 SUIT_DataObject* obj = dataObject( item );
823 QMap<int, int>::iterator it = myColumnIds.begin();
824 for( ; it != myColumnIds.end(); ++it )
825 item->setText( it.data(), obj->text( it.key() ) );
831 bool OB_Browser::eventFilter(QObject* watched, QEvent* e)
833 if ( watched == myView && e->type() == QEvent::ContextMenu )
835 contextMenuRequest( (QContextMenuEvent*)e );
838 return QFrame::eventFilter(watched, e);
841 void OB_Browser::contextMenuPopup( QPopupMenu* menu )
843 DataObjectList selected;
844 getSelected( selected );
847 for ( DataObjectListIterator itr( selected ); itr.current() && !closed; ++itr )
848 closed = hasClosed( listViewItem( itr.current() ) );
851 menu->insertItem( tr( "MEN_EXPAND_ALL" ), this, SLOT( onExpand() ) );
854 void OB_Browser::expand( QListViewItem* item )
859 item->setOpen( true );
860 for ( QListViewItem* child = item->firstChild(); child; child = child->nextSibling() )
864 bool OB_Browser::hasClosed( QListViewItem* item ) const
869 if ( item->childCount() && !item->isOpen() )
873 for ( QListViewItem* child = item->firstChild(); child && !has; child = child->nextSibling() )
874 has = hasClosed( child );