Salome HOME
Some functions for columns management were added.
[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   return 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 QValueList<int> OB_Browser::columns() const
445 {
446   QValueList<int> lst;
447   for ( QMap<int, int>::ConstIterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
448     lst.append( it.key() );
449   return lst;
450 }
451
452 void OB_Browser::updateTree( SUIT_DataObject* o )
453 {
454   updateTree( o ? o : getRootObject(), false );
455 }
456
457 void OB_Browser::updateTree( SUIT_DataObject* obj, const bool notify )
458 {
459   if ( !obj )
460     return;
461
462   DataObjectKey curKey;
463   DataObjectMap selObjs, openObjs;
464   DataObjectKeyMap selKeys, openKeys;
465
466   int selNum = numberOfSelected();
467
468   SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
469
470   if ( notify )
471   {
472     bool upd = isAutoUpdate();
473     setAutoUpdate( false );
474     emit aboutRefresh();
475     setAutoUpdate( upd );
476   }
477
478   createConnections( obj );
479   updateView( obj );
480
481   restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
482
483   autoOpenBranches();
484
485   if ( selNum != numberOfSelected() )
486     emit selectionChanged();
487 }
488
489 void OB_Browser::replaceTree( SUIT_DataObject* src, SUIT_DataObject* trg )
490 {
491   if ( !src || !trg || src->root() != getRootObject() )
492     return;
493
494   DataObjectKey curKey;
495   DataObjectMap selObjs, openObjs;
496   DataObjectKeyMap selKeys, openKeys;
497
498   int selNum = numberOfSelected();
499
500   SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
501
502   SUIT_DataObject* parent = src->parent();
503   int pos = parent ? parent->childPos( src ) : -1;
504
505   src->setParent( 0 );
506
507   if ( src != trg && isAutoDeleteObjects() )
508     delete src;
509
510   if ( parent && pos != -1 )
511     parent->insertChild( trg, pos );
512
513   trg->setParent( parent );
514
515   createConnections( trg );
516   updateView( trg );
517
518   restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
519
520   autoOpenBranches();
521
522   if ( selNum != numberOfSelected() )
523     emit selectionChanged();
524 }
525
526 void OB_Browser::updateView( const SUIT_DataObject* theStartObj )
527 {
528   QListView* lv = listView();
529   if ( !lv )
530     return;
531
532   if ( !theStartObj || theStartObj->root() != getRootObject() )
533     return;
534
535   QListViewItem* after = 0;
536   QListViewItem* parent = 0;
537   QListViewItem* startItem = listViewItem( theStartObj );
538
539   if ( theStartObj->parent() )
540     parent = listViewItem( theStartObj->parent() );
541
542   QListViewItem* prv = 0;
543   QListViewItem* cur = parent ? parent->firstChild() : lv->firstChild();
544   while ( !after && cur )
545   {
546     if ( cur == startItem )
547       after = prv;
548
549     prv = cur;
550     cur = cur->nextSibling();
551   }
552
553   QPtrList<QListViewItem> delList;
554   if ( !startItem && theStartObj == getRootObject() )
555   {
556     for ( QListViewItem* item = lv->firstChild(); item; item = item->nextSibling() )
557       delList.append( item );
558   }
559   else
560     delList.append( startItem );
561
562   for ( QPtrListIterator<QListViewItem> it( delList ); it.current(); ++it )
563   {
564     removeReferences( it.current() );
565     delete it.current();
566   }
567
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 )
571   {
572     DataObjectList lst;
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 );
578   }
579   else
580     createTree( theStartObj, parent, after );
581 }
582
583 QListViewItem* OB_Browser::createTree( const SUIT_DataObject* obj,
584                                        QListViewItem* parent, QListViewItem* after )
585 {
586   if ( !obj )
587     return 0;
588   
589   QListViewItem* item = createItem( obj, parent, after );
590
591   DataObjectList lst;
592   obj->children( lst );
593   for ( DataObjectListIterator it ( lst ); it.current(); ++it )
594     createTree( it.current(), item );
595
596   return item;
597 }
598
599 QListViewItem* OB_Browser::createItem( const SUIT_DataObject* o,
600                                        QListViewItem* parent, QListViewItem* after )
601 {
602   QListView* lv = listView();
603
604   if ( !lv || !o )
605     return 0;
606
607   QListViewItem* item = 0;
608   SUIT_DataObject* obj = (SUIT_DataObject*)o;
609
610   int type = -1;
611
612   switch ( obj->checkType() )
613   {
614   case SUIT_DataObject::CheckBox:
615     type = QCheckListItem::CheckBox;
616     break;
617   case SUIT_DataObject::RadioButton:
618     type = QCheckListItem::RadioButton;
619     break;
620   }
621
622   if ( parent )
623   {
624     if ( parent->childCount() && !after )
625     {
626       after = parent->firstChild();
627       while ( after->nextSibling() )
628         after = after->nextSibling();
629     }
630
631     if ( after )
632     {
633       if ( type == -1 )
634         item = new OB_ListItem( obj, parent, after );
635       else
636         item = new OB_CheckListItem( obj, parent, after, (QCheckListItem::Type)type );
637     }
638     else
639     {
640       if ( type == -1 )
641         item = new OB_ListItem( obj, parent );
642       else
643         item = new OB_CheckListItem( obj, parent,  (QCheckListItem::Type)type );
644     }
645   }
646   else // ROOT item
647   {
648     if ( type == -1 )
649       item = new OB_ListItem( obj, lv );
650     else
651       item = new OB_CheckListItem( obj, lv,  (QCheckListItem::Type)type );
652   }
653
654   myItems.insert( obj, item );
655
656   updateText( item );
657
658   return item;
659 }
660
661 void OB_Browser::adjustWidth()
662 {
663   if ( !listView() )
664     return;
665
666   listView()->setColumnWidth( 0, 0 );
667   if ( listView()->firstChild() )
668     adjustWidth( listView()->firstChild() );
669 }
670
671 void OB_Browser::adjustWidth( QListViewItem* item )
672 {
673   while ( item )
674   {
675     item->widthChanged( 0 );
676     if ( item->isOpen() )
677       adjustWidth( item->firstChild() );
678     item = item->nextSibling();
679   }
680 }
681
682 SUIT_DataObject* OB_Browser::dataObject( const QListViewItem* item ) const
683 {
684   SUIT_DataObject* obj = 0;
685
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();
690
691   return obj;
692 }
693
694 QListViewItem* OB_Browser::listViewItem( const SUIT_DataObject* obj ) const
695 {
696   QListViewItem* item = 0;
697
698   if ( myItems.contains( (SUIT_DataObject*)obj ) )
699     item = myItems[(SUIT_DataObject*)obj];
700
701   return item;
702 }
703
704 QListView* OB_Browser::listView() const
705 {
706   return myView;
707 }
708
709 void OB_Browser::removeReferences( QListViewItem* item )
710 {
711   if ( !item )
712     return;
713
714   SUIT_DataObject* obj = dataObject( item );
715   myItems.remove( obj );
716
717   QListViewItem* i = item->firstChild();
718   while ( i )
719   {
720     removeReferences( i );
721     i = i->nextSibling();
722   }
723 }
724
725 void OB_Browser::createConnections( SUIT_DataObject* obj )
726 {
727   if ( !obj )
728     return;
729
730   DataObjectList childList;
731   obj->children( childList, true );
732
733   childList.prepend( obj );
734
735   for ( DataObjectListIterator it( childList ); it.current(); ++it )
736     it.current()->connect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
737 }
738
739 SUIT_DataObject* OB_Browser::storeState( DataObjectMap& selObjs, DataObjectMap& openObjs,
740                                          DataObjectKeyMap& selKeys, DataObjectKeyMap& openKeys,
741                                          DataObjectKey& curKey ) const
742 {
743   QListView* lv = listView();
744   if ( !lv )
745     return 0;
746
747   SUIT_DataObject* curObj = dataObject( lv->currentItem() );
748
749   curKey = objectKey( curObj );
750
751   for ( QListViewItemIterator it( lv ); it.current(); ++it )
752   {
753     SUIT_DataObject* obj = dataObject( it.current() );
754     if ( !obj )
755       continue;
756
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 );
763   }
764
765   return curObj;
766 }
767
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 )
771 {
772   QListView* lv = listView();
773   if ( !lv )
774     return;
775
776   bool block = lv->signalsBlocked();
777   lv->blockSignals( true );
778
779   QListViewItem* curItem = 0;
780   for ( QListViewItemIterator it( lv ); it.current(); ++it )
781   {
782     QListViewItem* item = it.current();
783     SUIT_DataObject* obj = dataObject( item );
784
785     if ( !obj )
786       continue;
787
788     DataObjectKey key = objectKey( obj );
789
790     if ( selObjs.contains( obj ) )
791     {
792       if ( selObjs[obj] && !lv->isSelected( item ) )
793         lv->setSelected( item, true );
794     }
795     else if ( !key.isNull() && selKeys.contains( key ) && !lv->isSelected( item ) )
796       lv->setSelected( item, true );
797
798     if ( openObjs.contains( obj ) )
799     {
800       if ( openObjs[obj] )
801         lv->setOpen( item, true );
802     }
803     else if ( !key.isNull() && openKeys.contains( key ) )
804       lv->setOpen( item, true );
805
806     if ( !curItem && ( curObj == obj || ( !curKey.isNull() && curKey == key )) )
807       curItem = item;
808   }
809
810   if ( curItem )
811     lv->setCurrentItem( curItem );
812
813   lv->blockSignals( block );
814 }
815
816 OB_Browser::DataObjectKey OB_Browser::objectKey( QListViewItem* i ) const
817 {
818   return objectKey( dataObject( i ) );
819 }
820
821 OB_Browser::DataObjectKey OB_Browser::objectKey( SUIT_DataObject* obj ) const
822 {
823   if ( !obj )
824     return 0;
825
826   return DataObjectKey( obj->key() );
827 }
828
829 void OB_Browser::keyPressEvent( QKeyEvent* e )
830 {
831   if ( e->key() == Qt::Key_F5 )
832     updateTree();
833
834   QFrame::keyPressEvent( e );
835 }
836
837 void OB_Browser::onExpand()
838 {
839   DataObjectList selected;
840   getSelected( selected );
841   for ( DataObjectListIterator itr( selected ); itr.current(); ++itr )
842     expand( listViewItem( itr.current() ) );
843 }
844
845 void OB_Browser::onRefresh()
846 {
847   updateTree( 0, true );
848 }
849
850 void OB_Browser::onDestroyed( SUIT_DataObject* obj )
851 {
852   removeObject( obj );
853 }
854
855 void OB_Browser::onDropped( QPtrList<QListViewItem> items, QListViewItem* item, int action )
856 {
857   SUIT_DataObject* obj = dataObject( item );
858   if ( !obj )
859     return;
860
861   DataObjectList lst;
862   for ( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it )
863   {
864     SUIT_DataObject* o = dataObject( it.current() );
865     if ( o )
866       lst.append( o );
867   }
868
869   if ( !lst.isEmpty() )
870     emit dropped( lst, obj, action );
871 }
872
873 void OB_Browser::updateText()
874 {
875   if ( myColumnIds.isEmpty() )
876     return;
877
878   QListView* lv = listView();
879   if ( !lv )
880     return;
881
882   for ( QListViewItemIterator it( lv ); it.current(); ++it )
883   {
884     SUIT_DataObject* obj = dataObject( it.current() );
885     if ( !obj )
886       continue;
887
888     for( QMap<int, int>::iterator itr = myColumnIds.begin(); itr != myColumnIds.end(); ++itr )
889       it.current()->setText( itr.data(), obj->text( itr.key() ) );
890   }
891 }
892
893 void OB_Browser::updateText( QListViewItem* item )
894 {
895   SUIT_DataObject* obj = dataObject( item );
896   if ( !obj )
897     return;
898
899   for( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
900     item->setText( it.data(), obj->text( it.key() ) );
901 }
902
903 bool OB_Browser::eventFilter( QObject* o, QEvent* e )
904 {
905   if ( o == myView && e->type() == QEvent::ContextMenu )
906   {
907     QContextMenuEvent* ce = (QContextMenuEvent*)e;
908     if ( ce->reason() != QContextMenuEvent::Mouse )
909       contextMenuRequest( ce );
910     return true;
911   }
912   if ( o == myView && e->type() == QEvent::MouseButtonRelease )
913   {
914     QMouseEvent* me = (QMouseEvent*)e;
915     if ( me->button() == RightButton )
916     {
917       QContextMenuEvent ce( QContextMenuEvent::Mouse, me->pos(), me->globalPos(), me->state() );
918       contextMenuRequest( &ce );
919       return true;
920     }
921   }
922
923   return QFrame::eventFilter( o, e );
924 }
925
926 void OB_Browser::contextMenuPopup( QPopupMenu* menu )
927 {
928   DataObjectList selected;
929   getSelected( selected );
930
931   bool closed = false;
932   for ( DataObjectListIterator itr( selected ); itr.current() && !closed; ++itr )
933     closed = hasClosed( listViewItem( itr.current() ) );
934
935   if ( closed )
936   {
937     menu->insertItem( tr( "MEN_EXPAND_ALL" ), this, SLOT( onExpand() ) );
938     menu->insertSeparator();
939   }
940   menu->insertItem( tr( "MEN_REFRESH" ), this, SLOT( onRefresh() ) );
941 }
942
943 void OB_Browser::expand( QListViewItem* item )
944 {
945   if ( !item )
946     return;
947
948   item->setOpen( true );
949   for ( QListViewItem* child = item->firstChild(); child; child = child->nextSibling() )
950     expand( child );
951 }
952
953 bool OB_Browser::hasClosed( QListViewItem* item ) const
954 {
955   if ( !item )
956     return false;
957
958   if ( item->childCount() && !item->isOpen() )
959     return true;
960
961   bool has = false;
962   for ( QListViewItem* child = item->firstChild(); child && !has; child = child->nextSibling() )
963     has = hasClosed( child );
964
965   return has;
966 }
967
968 void OB_Browser::removeObject( SUIT_DataObject* obj, const bool autoUpd )
969 {
970   if ( !obj )
971     return;
972
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 );
980
981   QListViewItem* item = listViewItem( obj );
982
983   myItems.remove( obj );
984
985   if ( obj == myRoot )
986     myRoot = 0;
987
988   if ( !autoUpd )
989     return;
990
991   if ( isAutoUpdate() )
992   {
993     SUIT_DataObject* pObj = item && item->parent() ? dataObject( item->parent() ) : 0;
994     updateTree( pObj );
995   }
996   else
997     delete item;
998 }
999
1000 void OB_Browser::autoOpenBranches()
1001 {
1002   int level = autoOpenLevel();
1003   QListView* lv = listView();
1004   if ( !lv || level < 1 )
1005     return;
1006
1007   QListViewItem* item = lv->firstChild();
1008   while ( item )
1009   {
1010     openBranch( item, level );
1011     item = item->nextSibling();
1012   }
1013 }
1014
1015 void OB_Browser::openBranch( QListViewItem* item, const int level )
1016 {
1017   if ( !item || level < 1 || !item->childCount() )
1018     return;
1019
1020   item->setOpen( true );
1021   while ( item )
1022   {
1023     openBranch( item, level - 1 );
1024     item = item->nextSibling();
1025   }
1026 }