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