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