Salome HOME
fe451d4b1ee423890ba926da32c676db6f0fefb6
[modules/gui.git] / src / ObjBrowser / OB_Browser.cxx
1 #include "OB_Browser.h"
2
3 #include "OB_Filter.h"
4 #include "OB_ListItem.h"
5 #include "OB_ListView.h"
6
7 #include <qcursor.h>
8 #include <qlayout.h>
9 #include <qtooltip.h>
10 #include <qpainter.h>
11 #include <qwmatrix.h>
12 #include <qlistview.h>
13 #include <qpopupmenu.h>
14
15 /*!
16     Class: OB_Browser::ToolTip
17     Descr: Tool tip for OB_Browser.
18 */
19
20 class OB_Browser::ToolTip : public QToolTip
21 {
22 public:
23   ToolTip( OB_Browser* b, QWidget* p = 0 );
24   virtual ~ToolTip();
25
26   void        maybeTip( const QPoint& );
27
28 private:
29   OB_Browser* myBrowser;
30 };
31
32 OB_Browser::ToolTip::ToolTip( OB_Browser* b, QWidget* p )
33 : QToolTip( p ),
34 myBrowser( b )
35 {
36 }
37
38 OB_Browser::ToolTip::~ToolTip()
39 {
40 }
41
42 void OB_Browser::ToolTip::maybeTip( const QPoint& pos )
43 {
44   if ( !parentWidget() || !myBrowser || !myBrowser->isShowToolTips() )
45           return;
46
47   QListView* lv = myBrowser->listView();
48
49   QListViewItem* item = lv->itemAt( pos );
50   SUIT_DataObject* obj = myBrowser->dataObject( item );
51   if ( !obj )
52     return;
53
54   QString aText = obj->toolTip();
55
56   if ( aText.isEmpty() )
57     return;
58
59   QRect aRect = lv->itemRect( item );
60
61   tip( aRect, aText );
62 }
63
64 /*!
65     Class: OB_Browser
66     Descr: Hierarchical tree object browser.
67 */
68
69 OB_Browser::OB_Browser( QWidget* parent, SUIT_DataObject* root )
70 : QFrame( parent ),
71
72 myRoot( 0 ),
73 myTooltip( 0 ),
74 myAutoOpenLevel( 0 ),
75 myAutoUpdate( false ),
76 myAutoDelObjs( false ),
77 myRootDecorated( true )
78 {
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
86   QVBoxLayout* main = new QVBoxLayout( this );
87   main->addWidget( myView );
88
89   myShowToolTips = true;
90   myTooltip = new ToolTip( this, myView->viewport() );
91
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() ) );
95
96   setRootObject( root );
97 }
98
99 OB_Browser::~OB_Browser()
100 {
101   myItems.clear();
102   delete myTooltip;
103 }
104
105 bool OB_Browser::rootIsDecorated() const
106 {
107   return myRootDecorated;
108 }
109
110 void OB_Browser::setRootIsDecorated( const bool decor )
111 {
112   if ( decor == rootIsDecorated() ) 
113     return;
114
115   myRootDecorated = decor;
116   updateTree();
117 }
118
119 int OB_Browser::autoOpenLevel() const
120 {
121   return myAutoOpenLevel;
122 }
123
124 void OB_Browser::setAutoOpenLevel( const int level )
125 {
126   if ( myAutoOpenLevel == level )
127     return;
128
129   myAutoOpenLevel = level;
130
131   autoOpenBranches();
132 }
133
134 bool OB_Browser::isShowToolTips()
135 {
136   return myShowToolTips;
137 }
138
139 void OB_Browser::setShowToolTips( const bool theDisplay )
140 {
141   myShowToolTips = theDisplay;
142 }
143
144 bool OB_Browser::isAutoUpdate() const
145 {
146   return myAutoUpdate;
147 }
148
149 void OB_Browser::setAutoUpdate( const bool on )
150 {
151   myAutoUpdate = on;
152 }
153
154 bool OB_Browser::isAutoDeleteObjects() const
155 {
156   return myAutoDelObjs;
157 }
158
159 void OB_Browser::setAutoDeleteObjects( const bool on )
160 {
161   myAutoDelObjs = on;
162 }
163
164 SUIT_DataObject* OB_Browser::getRootObject() const
165 {
166   return myRoot;
167 }
168
169 void OB_Browser::setRootObject( SUIT_DataObject* theRoot )
170 {
171   DataObjectKey curKey;
172   DataObjectMap selObjs, openObjs;
173   DataObjectKeyMap selKeys, openKeys;
174
175   int selNum = numberOfSelected();
176
177   SUIT_DataObject* curObj = 0;
178   if ( theRoot )
179     curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
180
181   if ( myRoot != theRoot && isAutoDeleteObjects() )
182     delete myRoot;
183
184   myRoot = theRoot;
185
186   createConnections( myRoot );
187
188   if ( myRoot )
189     updateView( myRoot );
190   else if ( listView() )
191   {
192     myItems.clear();
193     listView()->clear();
194   }
195
196   restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
197
198   autoOpenBranches();
199
200   if ( selNum != numberOfSelected() )
201     emit selectionChanged();
202 }
203
204 int OB_Browser::numberOfSelected() const
205 {
206   int count = 0;
207   if ( listView() )
208   {
209     for ( QListViewItemIterator it( listView() ); it.current(); ++it )
210       if ( it.current()->isSelected() ) 
211         count++;
212   }
213   return count;
214 }
215
216 DataObjectList OB_Browser::getSelected() const
217 {
218   DataObjectList lst;
219   getSelected( lst );
220   return lst;
221 }
222
223 void OB_Browser::getSelected( DataObjectList& theObjList ) const
224 {
225   theObjList.clear();
226
227   if ( !listView() )
228     return;
229
230   for ( QListViewItemIterator it( listView() ); it.current(); ++it )
231   {
232     if ( it.current()->isSelected() ) 
233     {
234       SUIT_DataObject* obj = dataObject( it.current() );
235       if ( obj )
236         theObjList.append( obj );
237     }
238   }
239 }
240
241 void OB_Browser::setSelected( const SUIT_DataObject* theObject, const bool append )
242 {
243   DataObjectList lst;
244   lst.append( theObject );
245   setSelected( lst, append );
246 }
247
248 void OB_Browser::setSelected( const DataObjectList& theObjLst, const bool append )
249 {
250   QListView* lv = listView();
251
252   if ( !lv )
253     return;
254
255   bool changed = false;
256   bool block = lv->signalsBlocked();
257   lv->blockSignals( true );
258
259   QMap<QListViewItem*, int> map;
260   for ( DataObjectListIterator itr( theObjLst ); itr.current(); ++itr )
261     map.insert( listViewItem( itr.current() ), 0 );
262
263   for ( QListViewItemIterator it( lv ); it.current(); ++it )
264   {
265     QListViewItem* item = it.current();
266     if ( map.contains( item ) && !lv->isSelected( item ) )
267     {
268       changed = true;
269       lv->setSelected( item, true );
270     }
271     if ( !append && !map.contains( item ) && lv->isSelected( item ) )
272     {
273       changed = true;
274       lv->setSelected( item, false );
275     }
276   }
277
278   lv->blockSignals( block );
279
280   if ( changed )
281   {
282     int count = 0;
283     QListViewItem* sel = 0;
284     QListViewItem* cur = lv->currentItem();
285     for ( QListViewItemIterator iter( lv ); iter.current() && !sel; ++iter, count++ )
286     {
287       if ( iter.current()->isSelected() && cur == iter.current() )
288         sel = iter.current();
289     }
290
291     for ( QListViewItemIterator itr( lv ); itr.current() && !sel; ++itr )
292     {
293       if ( itr.current()->isSelected() )
294               sel = itr.current();
295     }
296
297     if ( sel )
298       lv->setCurrentItem( sel );
299
300     if ( sel && count == 1 )
301       lv->ensureItemVisible( sel );
302
303     emit selectionChanged();
304   }
305 }
306
307 bool OB_Browser::isOpen( SUIT_DataObject* theObject ) const
308 {
309   bool res = false;
310   if ( listView() )
311     res = listView()->isOpen( listViewItem( theObject ) );
312   return res;
313 }
314
315 void OB_Browser::setOpen( SUIT_DataObject* theObject, const bool theOpen )
316 {
317   if ( listView() )
318     listView()->setOpen( listViewItem( theObject ), theOpen );
319 }
320
321 SUIT_DataObject* OB_Browser::dataObjectAt( const QPoint& pos ) const
322 {
323   SUIT_DataObject* obj = 0;
324
325   QListView* lv = listView();
326   if ( lv )
327     obj = dataObject( lv->itemAt( pos ) );
328
329   return obj;
330 }
331
332 OB_Filter* OB_Browser::filter() const
333 {
334   return myView->filter();
335 }
336
337 void OB_Browser::setFilter( OB_Filter* f )
338 {
339   myView->setFilter( f );
340 }
341
342 int OB_Browser::addColumn( const QString& label, const int id, const int width )
343 {
344   return addColumn( QIconSet(), label, id, width );
345 }
346
347 int OB_Browser::addColumn( const QIconSet& icon, const QString& label, const int id, const int width )
348 {
349   QListView* lv = listView();
350   if ( !lv )
351     return -1;
352
353   int theId = id;
354   if ( theId < 0 )
355   {
356     while ( myColumnIds.contains( theId ) )
357       theId++;
358   }
359
360   if ( myColumnIds.contains( theId ) )
361     return -1; // can not reuse id
362
363   int sec = -1;
364   if ( icon.isNull() )
365     sec = lv->addColumn( label, width );
366   else
367     sec = lv->addColumn( icon, label, width );
368
369   if ( sec == -1 )
370     return -1;
371
372   myColumnIds.insert( theId, sec );
373   updateText();
374
375   return theId;
376 }
377
378 void OB_Browser::removeColumn( const int id )
379 {
380   QListView* lv = listView();
381   if ( !lv || !myColumnIds.contains( id ) )
382     return;
383
384   int sec = myColumnIds[id];
385   lv->removeColumn( sec );
386
387   // update map of column indeces
388   myColumnIds.remove( id );
389   for ( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
390   {
391     if ( it.key() > id )
392       it.data()--;
393   }
394   updateText();
395 }
396
397 void OB_Browser::setNameTitle( const QString& label )
398 {
399   setNameTitle( QIconSet(), label );
400 }
401
402 void OB_Browser::setNameTitle( const QIconSet& icon, const QString& label )
403 {
404   QListView* lv = listView();
405   if ( !lv )
406     return;
407
408   if ( icon.isNull() )
409     lv->setColumnText( 0, label );
410   else
411     lv->setColumnText( 0, icon, label );
412 }
413
414 void OB_Browser::setColumnTitle( const int id, const QString& label )
415 {
416   setColumnTitle( id, QIconSet(), label );
417 }
418
419 void OB_Browser::setColumnTitle( const int id, const QIconSet& icon, const QString& label )
420 {
421   QListView* lv = listView();
422   if ( !lv || !myColumnIds.contains( id ) )
423     return;
424
425   if ( icon.isNull() )
426     lv->setColumnText( myColumnIds[id], label );
427   else
428     lv->setColumnText( myColumnIds[id], icon, label );
429 }
430
431 bool OB_Browser::isColumnVisible( const int id ) const
432 {
433   myColumnIds.contains( id ) && myView->isShown( myColumnIds[id] );
434 }
435
436 void OB_Browser::setColumnShown( const int id, const bool on )
437 {
438   if ( !myColumnIds.contains( id ) )
439     return;
440
441   myView->setShown( myColumnIds[id], on );
442 }
443
444 void OB_Browser::updateTree( SUIT_DataObject* o )
445 {
446   updateTree( o ? o : getRootObject(), false );
447 }
448
449 void OB_Browser::updateTree( SUIT_DataObject* obj, const bool notify )
450 {
451   if ( !obj )
452     return;
453
454   DataObjectKey curKey;
455   DataObjectMap selObjs, openObjs;
456   DataObjectKeyMap selKeys, openKeys;
457
458   int selNum = numberOfSelected();
459
460   SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
461
462   if ( notify )
463     emit aboutRefresh();
464
465   createConnections( obj );
466   updateView( obj );
467
468   restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
469
470   autoOpenBranches();
471
472   if ( selNum != numberOfSelected() )
473     emit selectionChanged();
474 }
475
476 void OB_Browser::replaceTree( SUIT_DataObject* src, SUIT_DataObject* trg )
477 {
478   if ( !src || !trg || src->root() != getRootObject() )
479     return;
480
481   DataObjectKey curKey;
482   DataObjectMap selObjs, openObjs;
483   DataObjectKeyMap selKeys, openKeys;
484
485   int selNum = numberOfSelected();
486
487   SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
488
489   SUIT_DataObject* parent = src->parent();
490   int pos = parent ? parent->childPos( src ) : -1;
491
492   src->setParent( 0 );
493
494   if ( src != trg && isAutoDeleteObjects() )
495     delete src;
496
497   if ( parent && pos != -1 )
498     parent->insertChild( trg, pos );
499
500   trg->setParent( parent );
501
502   createConnections( trg );
503   updateView( trg );
504
505   restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
506
507   autoOpenBranches();
508
509   if ( selNum != numberOfSelected() )
510     emit selectionChanged();
511 }
512
513 void OB_Browser::updateView( const SUIT_DataObject* theStartObj )
514 {
515   QListView* lv = listView();
516   if ( !lv )
517     return;
518
519   if ( !theStartObj || theStartObj->root() != getRootObject() )
520     return;
521
522   QListViewItem* after = 0;
523   QListViewItem* parent = 0;
524   QListViewItem* startItem = listViewItem( theStartObj );
525
526   if ( theStartObj->parent() )
527     parent = listViewItem( theStartObj->parent() );
528
529   QListViewItem* prv = 0;
530   QListViewItem* cur = parent ? parent->firstChild() : lv->firstChild();
531   while ( !after && cur )
532   {
533     if ( cur == startItem )
534       after = prv;
535
536     prv = cur;
537     cur = cur->nextSibling();
538   }
539
540   QPtrList<QListViewItem> delList;
541   if ( !startItem && theStartObj == getRootObject() )
542   {
543     for ( QListViewItem* item = lv->firstChild(); item; item = item->nextSibling() )
544       delList.append( item );
545   }
546   else
547     delList.append( startItem );
548
549   for ( QPtrListIterator<QListViewItem> it( delList ); it.current(); ++it )
550   {
551     removeReferences( it.current() );
552     delete it.current();
553   }
554
555   // for myRoot object, if myShowRoot==false, then creating multiple top-level QListViewItem-s
556   // (which will correspond to myRoot's children = Modules).  
557   if ( rootIsDecorated() && theStartObj == myRoot )
558   {
559     DataObjectList lst;
560     theStartObj->children( lst );
561     DataObjectListIterator it ( lst );
562     // iterating backward to preserve the order of elements in the tree
563     for ( it.toLast(); it.current(); --it )
564       createTree( it.current(), 0, 0 );
565   }
566   else
567     createTree( theStartObj, parent, after );
568 }
569
570 QListViewItem* OB_Browser::createTree( const SUIT_DataObject* obj,
571                                        QListViewItem* parent, QListViewItem* after )
572 {
573   if ( !obj )
574     return 0;
575   
576   QListViewItem* item = createItem( obj, parent, after );
577
578   DataObjectList lst;
579   obj->children( lst );
580   for ( DataObjectListIterator it ( lst ); it.current(); ++it )
581     createTree( it.current(), item );
582
583   return item;
584 }
585
586 QListViewItem* OB_Browser::createItem( const SUIT_DataObject* o,
587                                        QListViewItem* parent, QListViewItem* after )
588 {
589   QListView* lv = listView();
590
591   if ( !lv || !o )
592     return 0;
593
594   QListViewItem* item = 0;
595   SUIT_DataObject* obj = (SUIT_DataObject*)o;
596
597   int type = -1;
598
599   switch ( obj->checkType() )
600   {
601   case SUIT_DataObject::CheckBox:
602     type = QCheckListItem::CheckBox;
603     break;
604   case SUIT_DataObject::RadioButton:
605     type = QCheckListItem::RadioButton;
606     break;
607   }
608
609   if ( parent )
610   {
611     if ( parent->childCount() && !after )
612     {
613       after = parent->firstChild();
614       while ( after->nextSibling() )
615         after = after->nextSibling();
616     }
617
618     if ( after )
619     {
620       if ( type == -1 )
621         item = new OB_ListItem( obj, parent, after );
622       else
623         item = new OB_CheckListItem( obj, parent, after, (QCheckListItem::Type)type );
624     }
625     else
626     {
627       if ( type == -1 )
628         item = new OB_ListItem( obj, parent );
629       else
630         item = new OB_CheckListItem( obj, parent,  (QCheckListItem::Type)type );
631     }
632   }
633   else // ROOT item
634   {
635     if ( type == -1 )
636       item = new OB_ListItem( obj, lv );
637     else
638       item = new OB_CheckListItem( obj, lv,  (QCheckListItem::Type)type );
639   }
640
641   myItems.insert( obj, item );
642
643   updateText( item );
644
645   return item;
646 }
647
648 void OB_Browser::adjustWidth()
649 {
650   if ( !listView() )
651     return;
652
653   listView()->setColumnWidth( 0, 0 );
654   if ( listView()->firstChild() )
655     adjustWidth( listView()->firstChild() );
656 }
657
658 void OB_Browser::adjustWidth( QListViewItem* item )
659 {
660   while ( item )
661   {
662     item->widthChanged( 0 );
663     if ( item->isOpen() )
664       adjustWidth( item->firstChild() );
665     item = item->nextSibling();
666   }
667 }
668
669 SUIT_DataObject* OB_Browser::dataObject( const QListViewItem* item ) const
670 {
671   SUIT_DataObject* obj = 0;
672
673   if ( item && item->rtti() == OB_ListItem::RTTI() )
674     obj = ((OB_ListItem*)item)->dataObject();
675   else if ( item && item->rtti() == OB_CheckListItem::RTTI() )
676     obj = ((OB_CheckListItem*)item)->dataObject();
677
678   return obj;
679 }
680
681 QListViewItem* OB_Browser::listViewItem( const SUIT_DataObject* obj ) const
682 {
683   QListViewItem* item = 0;
684
685   if ( myItems.contains( (SUIT_DataObject*)obj ) )
686     item = myItems[(SUIT_DataObject*)obj];
687
688   return item;
689 }
690
691 QListView* OB_Browser::listView() const
692 {
693   return myView;
694 }
695
696 void OB_Browser::removeReferences( QListViewItem* item )
697 {
698   if ( !item )
699     return;
700
701   SUIT_DataObject* obj = dataObject( item );
702   myItems.remove( obj );
703
704   QListViewItem* i = item->firstChild();
705   while ( i )
706   {
707     removeReferences( i );
708     i = i->nextSibling();
709   }
710 }
711
712 void OB_Browser::createConnections( SUIT_DataObject* obj )
713 {
714   if ( !obj )
715     return;
716
717   DataObjectList childList;
718   obj->children( childList, true );
719
720   childList.prepend( obj );
721
722   for ( DataObjectListIterator it( childList ); it.current(); ++it )
723     it.current()->connect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
724 }
725
726 SUIT_DataObject* OB_Browser::storeState( DataObjectMap& selObjs, DataObjectMap& openObjs,
727                                          DataObjectKeyMap& selKeys, DataObjectKeyMap& openKeys,
728                                          DataObjectKey& curKey ) const
729 {
730   QListView* lv = listView();
731   if ( !lv )
732     return 0;
733
734   SUIT_DataObject* curObj = dataObject( lv->currentItem() );
735
736   curKey = objectKey( curObj );
737
738   for ( QListViewItemIterator it( lv ); it.current(); ++it )
739   {
740     SUIT_DataObject* obj = dataObject( it.current() );
741     if ( !obj )
742       continue;
743
744     selObjs.insert( obj, lv->isSelected( it.current() ) );
745     openObjs.insert( obj, lv->isOpen( it.current() ) );
746     if ( lv->isSelected( it.current() ) )
747       selKeys.insert( objectKey( obj ), 0 );
748     if ( lv->isOpen( it.current() ) )
749       openKeys.insert( objectKey( obj ), 0 );
750   }
751
752   return curObj;
753 }
754
755 void OB_Browser::restoreState( const DataObjectMap& selObjs, const DataObjectMap& openObjs,
756                                const SUIT_DataObject* curObj, const DataObjectKeyMap& selKeys,
757                                const DataObjectKeyMap& openKeys, const DataObjectKey& curKey )
758 {
759   QListView* lv = listView();
760   if ( !lv )
761     return;
762
763   bool block = lv->signalsBlocked();
764   lv->blockSignals( true );
765
766   QListViewItem* curItem = 0;
767   for ( QListViewItemIterator it( lv ); it.current(); ++it )
768   {
769     QListViewItem* item = it.current();
770     SUIT_DataObject* obj = dataObject( item );
771
772     if ( !obj )
773       continue;
774
775     DataObjectKey key = objectKey( obj );
776
777     if ( selObjs.contains( obj ) )
778     {
779       if ( selObjs[obj] && !lv->isSelected( item ) )
780         lv->setSelected( item, true );
781     }
782     else if ( !key.isNull() && selKeys.contains( key ) && !lv->isSelected( item ) )
783       lv->setSelected( item, true );
784
785     if ( openObjs.contains( obj ) )
786     {
787       if ( openObjs[obj] )
788         lv->setOpen( item, true );
789     }
790     else if ( !key.isNull() && openKeys.contains( key ) )
791       lv->setOpen( item, true );
792
793     if ( !curItem && ( curObj == obj || ( !curKey.isNull() && curKey == key )) )
794       curItem = item;
795   }
796
797   if ( curItem )
798     lv->setCurrentItem( curItem );
799
800   lv->blockSignals( block );
801 }
802
803 OB_Browser::DataObjectKey OB_Browser::objectKey( QListViewItem* i ) const
804 {
805   return objectKey( dataObject( i ) );
806 }
807
808 OB_Browser::DataObjectKey OB_Browser::objectKey( SUIT_DataObject* obj ) const
809 {
810   if ( !obj )
811     return 0;
812
813   return DataObjectKey( obj->key() );
814 }
815
816 void OB_Browser::keyPressEvent( QKeyEvent* e )
817 {
818   if ( e->key() == Qt::Key_F5 )
819     updateTree();
820
821   QFrame::keyPressEvent( e );
822 }
823
824 void OB_Browser::onExpand()
825 {
826   DataObjectList selected;
827   getSelected( selected );
828   for ( DataObjectListIterator itr( selected ); itr.current(); ++itr )
829     expand( listViewItem( itr.current() ) );
830 }
831
832 void OB_Browser::onRefresh()
833 {
834   updateTree( 0, true );
835 }
836
837 void OB_Browser::onDestroyed( SUIT_DataObject* obj )
838 {
839   removeObject( obj );
840 }
841
842 void OB_Browser::onDropped( QPtrList<QListViewItem> items, QListViewItem* item, int action )
843 {
844   SUIT_DataObject* obj = dataObject( item );
845   if ( !obj )
846     return;
847
848   DataObjectList lst;
849   for ( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it )
850   {
851     SUIT_DataObject* o = dataObject( it.current() );
852     if ( o )
853       lst.append( o );
854   }
855
856   if ( !lst.isEmpty() )
857     emit dropped( lst, obj, action );
858 }
859
860 void OB_Browser::updateText()
861 {
862   if ( myColumnIds.isEmpty() )
863     return;
864
865   QListView* lv = listView();
866   if ( !lv )
867     return;
868
869   for ( QListViewItemIterator it( lv ); it.current(); ++it )
870   {
871     SUIT_DataObject* obj = dataObject( it.current() );
872     if ( !obj )
873       continue;
874
875     for( QMap<int, int>::iterator itr = myColumnIds.begin(); itr != myColumnIds.end(); ++itr )
876       it.current()->setText( itr.data(), obj->text( itr.key() ) );
877   }
878 }
879
880 void OB_Browser::updateText( QListViewItem* item )
881 {
882   SUIT_DataObject* obj = dataObject( item );
883   if ( !obj )
884     return;
885
886   for( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
887     item->setText( it.data(), obj->text( it.key() ) );
888 }
889
890 bool OB_Browser::eventFilter(QObject* watched, QEvent* e)
891 {
892   if ( watched == myView && e->type() == QEvent::ContextMenu )
893   {
894     contextMenuRequest( (QContextMenuEvent*)e );
895     return true;
896   }
897   return QFrame::eventFilter(watched, e);
898 }
899
900 void OB_Browser::contextMenuPopup( QPopupMenu* menu )
901 {
902   DataObjectList selected;
903   getSelected( selected );
904
905   bool closed = false;
906   for ( DataObjectListIterator itr( selected ); itr.current() && !closed; ++itr )
907     closed = hasClosed( listViewItem( itr.current() ) );
908
909   if ( closed )
910   {
911     menu->insertItem( tr( "MEN_EXPAND_ALL" ), this, SLOT( onExpand() ) );
912     menu->insertSeparator();
913   }
914   menu->insertItem( tr( "MEN_REFRESH" ), this, SLOT( onRefresh() ) );
915 }
916
917 void OB_Browser::expand( QListViewItem* item )
918 {
919   if ( !item )
920     return;
921
922   item->setOpen( true );
923   for ( QListViewItem* child = item->firstChild(); child; child = child->nextSibling() )
924     expand( child );
925 }
926
927 bool OB_Browser::hasClosed( QListViewItem* item ) const
928 {
929   if ( !item )
930     return false;
931
932   if ( item->childCount() && !item->isOpen() )
933     return true;
934
935   bool has = false;
936   for ( QListViewItem* child = item->firstChild(); child && !has; child = child->nextSibling() )
937     has = hasClosed( child );
938
939   return has;
940 }
941
942 void OB_Browser::removeObject( SUIT_DataObject* obj, const bool autoUpd )
943 {
944   if ( !obj )
945     return;
946
947   // Removing list view items from <myItems> recursively for all children.
948   // Otherwise, "delete item" line will destroy all item's children,
949   // and <myItems> will contain invalid pointers (see ~QListViewItem() description in Qt docs)
950   DataObjectList childList;
951   obj->children( childList );
952   for ( DataObjectListIterator it( childList ); it.current(); ++it )
953     removeObject( it.current(), false );
954
955   QListViewItem* item = listViewItem( obj );
956
957   myItems.remove( obj );
958
959   if ( obj == myRoot )
960     myRoot = 0;
961
962   if ( !autoUpd )
963     return;
964
965   if ( isAutoUpdate() )
966   {
967     SUIT_DataObject* pObj = item && item->parent() ? dataObject( item->parent() ) : 0;
968     updateTree( pObj );
969   }
970   else
971     delete item;
972 }
973
974 void OB_Browser::autoOpenBranches()
975 {
976   int level = autoOpenLevel();
977   QListView* lv = listView();
978   if ( !lv || level < 1 )
979     return;
980
981   QListViewItem* item = lv->firstChild();
982   while ( item )
983   {
984     openBranch( item, level );
985     item = item->nextSibling();
986   }
987 }
988
989 void OB_Browser::openBranch( QListViewItem* item, const int level )
990 {
991   if ( !item || level < 1 || !item->childCount() )
992     return;
993
994   item->setOpen( true );
995   while ( item )
996   {
997     openBranch( item, level - 1 );
998     item = item->nextSibling();
999   }
1000 }