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