Salome HOME
8ce6cd08c45c50a7783bf7a9d8a3ce37adadc958
[modules/geom.git] / src / DependencyTree / DependencyTree_View.cxx
1 // Copyright (C) 2014-2015  CEA/DEN, EDF R&D, OPEN CASCADE
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, or (at your option) any later version.
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/ or email : webmaster.salome@opencascade.com
18 //
19
20 // Internal includes
21 #include "DependencyTree_View.h"
22 #include "DependencyTree_Object.h"
23 #include "DependencyTree_Arrow.h"
24
25 // GUI includes
26 #include <SUIT_Session.h>
27 #include <SUIT_ResourceMgr.h>
28 #include <SalomeApp_Study.h>
29 #include <QtxActionToolMgr.h>
30 #include <LightApp_SelectionMgr.h>
31 #include <SALOME_ListIO.hxx>
32
33 // GEOM includes
34 #include <GEOMBase.h>
35
36 // Qt includes
37 #include <QApplication>
38 #include <QWidgetAction>
39 #include <QWheelEvent>
40
41 DependencyTree_View::DependencyTree_View( QWidget* theParent )
42 :GraphicsView_ViewPort( theParent ),
43 myLevelsNumber(0),
44 myMaxDownwardLevelsNumber(0),
45 myMaxUpwardLevelsNumber(0),
46 myIsUpdate( true )
47 {
48   SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() );
49   if ( !app ) return;
50
51   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( app->activeStudy() );
52   myStudy = GeometryGUI::ClientStudyToStudy( study->studyDS());
53
54   mySelectionMgr = app->selectionMgr();
55   if ( !mySelectionMgr ) return;
56
57   myMainEntries = new GEOM::string_array();
58
59   getNewTreeModel();
60 }
61
62 DependencyTree_View::~DependencyTree_View()
63 {
64   clearView( true );
65 }
66
67 //=================================================================================
68 // function : init()
69 // purpose  : this method is obligatory for initialize view frame actions
70 //=================================================================================
71 void DependencyTree_View::init( GraphicsView_ViewFrame* theViewFrame )
72 {
73   myNodesMovable = new QCheckBox( tr( "MOVE_NODES" ) );
74   QWidgetAction* nodesMovableAction = new QWidgetAction( theViewFrame );
75   nodesMovableAction->setDefaultWidget( myNodesMovable );
76
77   myDisplayAscendants = new QCheckBox( tr( "DISPLAY_ASCENDANTS" ) );
78   QWidgetAction* displayAscendantsAction = new QWidgetAction( theViewFrame );
79   displayAscendantsAction->setDefaultWidget( myDisplayAscendants  );
80
81   myDisplayDescendants = new QCheckBox(tr("DISPLAY_DESCENDANTS"));
82   QWidgetAction* displayDescendantsAction = new QWidgetAction( theViewFrame );
83   displayDescendantsAction->setDefaultWidget( myDisplayDescendants );
84
85   QLabel* hierarchyDepthLabel = new QLabel( tr( "HIERARCHY_DEPTH" ) );
86   QWidgetAction* hierarchyDepthLabelAction = new QWidgetAction( theViewFrame );
87   hierarchyDepthLabelAction->setDefaultWidget( hierarchyDepthLabel );
88
89   myLevelsNumber = checkMaxLevelsNumber();
90
91   myHierarchyDepth = new QSpinBox();
92   myHierarchyDepth->setRange( 0, checkMaxLevelsNumber() );
93   myHierarchyDepth->setSpecialValueText( tr( "SHOW_ALL" ) );
94   myHierarchyDepth->setValue( 0 );
95   QWidgetAction* hierarchyDepthAction = new QWidgetAction( theViewFrame );
96   hierarchyDepthAction->setDefaultWidget( myHierarchyDepth );
97
98   updateButton = new QPushButton( tr( "UPDATE" ) );
99   QWidgetAction* updateAction = new QWidgetAction( theViewFrame );
100   updateAction->setDefaultWidget( updateButton );
101
102   QAction* separator1 = theViewFrame->toolMgr()->separator( false );
103   QAction* separator2 = theViewFrame->toolMgr()->separator( false );
104
105   theViewFrame->toolMgr()->append( separator1, theViewFrame->getToolBarId() );
106   theViewFrame->toolMgr()->append( hierarchyDepthLabelAction, theViewFrame->getToolBarId() );
107   theViewFrame->toolMgr()->append( hierarchyDepthAction, theViewFrame->getToolBarId() );
108   theViewFrame->toolMgr()->append( displayAscendantsAction, theViewFrame->getToolBarId() );
109   theViewFrame->toolMgr()->append( displayDescendantsAction, theViewFrame->getToolBarId() );
110   theViewFrame->toolMgr()->append( nodesMovableAction, theViewFrame->getToolBarId() );
111
112   theViewFrame->toolMgr()->append( separator2, theViewFrame->getToolBarId() );
113   theViewFrame->toolMgr()->append( updateAction, theViewFrame->getToolBarId() );
114
115   connect( myNodesMovable, SIGNAL( toggled( bool ) ), this, SLOT( onMoveNodes( bool ) ) );
116   connect( myHierarchyDepth, SIGNAL( valueChanged ( int ) ), this, SLOT( onHierarchyType() ) );
117   connect( myDisplayAscendants , SIGNAL( toggled( bool ) ), this, SLOT( onHierarchyType() ) );
118   connect( myDisplayDescendants, SIGNAL( toggled( bool ) ), this, SLOT( onHierarchyType() ) );
119   connect( updateButton, SIGNAL( clicked() ), this, SLOT( onUpdateModel() ) );
120
121   SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() );
122   GeometryGUI* aGeomGUI = dynamic_cast<GeometryGUI*>( app->module( "Geometry" ) );
123   if ( aGeomGUI ) {
124     connect( aGeomGUI, SIGNAL( SignalDependencyTreeParamChanged( const QString&, const QString& ) ),
125              this, SLOT( onPreferenceChanged( const QString&, const QString& ) ) );
126     connect( aGeomGUI, SIGNAL( SignalDependencyTreeRenameObject( const QString& ) ),
127              this, SLOT( onRenameObject( const QString& ) ) );
128   }
129
130   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
131   setPrefBackgroundColor( resMgr->colorValue( "Geometry", "dependency_tree_background_color", QColor( 255, 255, 255 ) ) );
132   setNodesMovable( resMgr->booleanValue( "Geometry", "dependency_tree_move_nodes", true ) );
133   setHierarchyType( resMgr->integerValue( "Geometry", "dependency_tree_hierarchy_type", 0 ) );
134 }
135
136 //=================================================================================
137 // function : updateModel()
138 // purpose  : run all stage of dependency tree creation
139 //=================================================================================
140 void DependencyTree_View::updateModel( bool theUseSelectedObject, bool theUseOB )
141 {
142   getNewTreeModel( theUseSelectedObject, theUseOB );
143   onHierarchyType();
144 }
145
146 //=================================================================================
147 // function : mouseMoveEvent()
148 // purpose  : make some actions when mouse was moved
149 //=================================================================================
150 void DependencyTree_View::mouseMoveEvent( QMouseEvent *event )
151 {
152   QGraphicsView::mouseMoveEvent( event );
153   ArrowsInfo::const_iterator i;
154   for( i = myArrows.begin(); i != myArrows.end(); i++ ) {
155     if( DependencyTree_Arrow* arrow = myArrows[ i->first ] )
156       arrow->update();
157   }
158 }
159
160 //=================================================================================
161 // function : wheelEvent()
162 // purpose  : add zoom action when wheel is spinning
163 //=================================================================================
164 void DependencyTree_View::wheelEvent( QWheelEvent* event )
165 {
166   int inc = 10; // zoom coefficient
167   double cx = width() / 2;
168   double cy = height() / 2;
169   if( event->delta() > 0 )
170     zoom( cx, cy, cx + inc, cy + inc );
171   else
172     zoom( cx, cy, cx - inc, cy - inc );
173
174   QGraphicsView::wheelEvent( event );
175 }
176
177 //=================================================================================
178 // function : getViewName()
179 // purpose  : return the name of current view
180 //=================================================================================
181 QString DependencyTree_View::getViewName() const
182 {
183   return tr( "DEPENDENCY_TREE" );
184 }
185
186 //=================================================================================
187 // function : getStudyId()
188 // purpose  : return Id of current study
189 //=================================================================================
190 int DependencyTree_View::getStudyId() const
191 {
192   return myStudy->StudyId();
193 }
194
195 //=================================================================================
196 // function : getObjectByEntry()
197 // purpose  : return DependencyTree_Object by entry
198 //=================================================================================
199 DependencyTree_Object* DependencyTree_View::getObjectByEntry( const std::string& theEntry )
200 {
201   return myTreeMap[ theEntry ];
202 }
203
204 //=================================================================================
205 // function : setHierarchyType()
206 // purpose  : set hierarchy type of dependency tree
207 //=================================================================================
208 void DependencyTree_View::setHierarchyType( const int theType )
209 {
210   myIsUpdate = false;
211   switch( theType ) {
212   case 0:
213     myDisplayAscendants->setChecked( true );
214     myDisplayDescendants->setChecked( true );
215     break;
216   case 1:
217     myDisplayAscendants->setChecked( true );
218     myDisplayDescendants->setChecked( false );
219     break;
220   case 2:
221     myDisplayAscendants->setChecked( false );
222     myDisplayDescendants->setChecked( true );
223     break;
224   }
225   myIsUpdate = true;
226   myLevelsNumber = checkMaxLevelsNumber();
227   onHierarchyType();
228 }
229
230 //=================================================================================
231 // function : setNodesMovable()
232 // purpose  : set possibility to move nodes or not
233 //=================================================================================
234 void DependencyTree_View::setNodesMovable( const bool theIsMovable )
235 {
236   myNodesMovable->setChecked( theIsMovable );
237 }
238
239 //=================================================================================
240 // function : setPrefBackgroundColor()
241 // purpose  : set background color from preferences
242 //=================================================================================
243 void DependencyTree_View::setPrefBackgroundColor( const QColor& theColor )
244 {
245   if( isForegroundEnabled() )
246   {
247     setForegroundColor( theColor );
248     updateForeground();
249   }
250   else
251     setBackgroundColor( theColor );
252 }
253
254 //=================================================================================
255 // function : setNodeColor()
256 // purpose  : set node color from preferences
257 //=================================================================================
258 void DependencyTree_View::setNodeColor( const QColor& theColor )
259 {
260   EntryObjectMap::const_iterator i;
261   for( i = myTreeMap.begin(); i != myTreeMap.end(); i++ ) {
262     DependencyTree_Object* object = myTreeMap[ i->first ];
263     object->setColor( theColor );
264   }
265 }
266
267 //=================================================================================
268 // function : setMainNodeColor()
269 // purpose  : set main node color from preferences
270 //=================================================================================
271 void DependencyTree_View::setMainNodeColor( const QColor& theColor )
272 {
273   EntryObjectMap::const_iterator i;
274   for( i = myTreeMap.begin(); i != myTreeMap.end(); i++ ) {
275     DependencyTree_Object* object = myTreeMap[ i->first ];
276     object->setMainObjectColor( theColor );
277   }
278 }
279
280 //=================================================================================
281 // function : setUnpublishNodeColor()
282 // purpose  : set unpublished node color from preferences
283 //=================================================================================
284 void DependencyTree_View::setUnpublishNodeColor( const QColor& theColor )
285 {
286   EntryObjectMap::const_iterator i;
287   for( i = myTreeMap.begin(); i != myTreeMap.end(); i++ ) {
288     DependencyTree_Object* object = myTreeMap[ i->first ];
289     object->setUnpublishObjectColor( theColor );
290   }
291 }
292
293 //=================================================================================
294 // function : setSelectNodeColor()
295 // purpose  : set selected node color from preferences
296 //=================================================================================
297 void DependencyTree_View::setSelectNodeColor( const QColor& theColor )
298 {
299   EntryObjectMap::const_iterator i;
300   for( i = myTreeMap.begin(); i != myTreeMap.end(); i++ ) {
301     DependencyTree_Object* object = myTreeMap[ i->first ];
302     object->setSelectColor( theColor );
303   }
304 }
305
306 //=================================================================================
307 // function : setArrowColor()
308 // purpose  : set arrow color from preferences
309 //=================================================================================
310 void DependencyTree_View::setArrowColor( const QColor& theColor )
311 {
312   ArrowsInfo::const_iterator i;
313   for( i = myArrows.begin(); i != myArrows.end(); i++ ) {
314     DependencyTree_Arrow* arrow = myArrows[ i->first ];
315     arrow->setColor( theColor );
316   }
317 }
318
319 //=================================================================================
320 // function : setHighlightArrowColor()
321 // purpose  : set highlighted arrow color from preferences
322 //=================================================================================
323 void DependencyTree_View::setHighlightArrowColor( const QColor& theColor )
324 {
325   ArrowsInfo::const_iterator i;
326   for( i = myArrows.begin(); i != myArrows.end(); i++ ) {
327     DependencyTree_Arrow* arrow = myArrows[ i->first ];
328     arrow->setHighlightColor( theColor );
329   }
330 }
331
332 //=================================================================================
333 // function : setSelectArrowColor()
334 // purpose  : set selected arrow color from preferences
335 //=================================================================================
336 void DependencyTree_View::setSelectArrowColor( const QColor& theColor )
337 {
338   ArrowsInfo::const_iterator i;
339   for( i = myArrows.begin(); i != myArrows.end(); i++ ) {
340     DependencyTree_Arrow* arrow = myArrows[ i->first ];
341     arrow->setSelectColor( theColor );
342   }
343 }
344
345 //=================================================================================
346 // function : onRebuildModel()
347 // purpose  : slot for updating tree model using selected objects in viewer
348 //=================================================================================
349 void DependencyTree_View::onRebuildModel()
350 {
351   updateModel( true, false );
352 }
353
354 //=================================================================================
355 // function : resizeEvent()
356 // purpose  : reimplemented from QGraphicsView::resizeEvent()
357 //=================================================================================
358 void DependencyTree_View::resizeEvent(QResizeEvent *event)
359 {
360   QPointF aCenter = mapToScene( event->oldSize().width()/2,
361                                 event->oldSize().height()/2 );
362   QGraphicsView::resizeEvent( event );
363   centerOn( aCenter.x(),aCenter.y() );
364 }
365
366 //=================================================================================
367 // function : onUpdateModel()
368 // purpose  : slot for updating tree model for main objects in viewer
369 //=================================================================================
370 void DependencyTree_View::onUpdateModel()
371 {
372   updateModel( false );
373 }
374
375 //=================================================================================
376 // function : onMoveNodes()
377 // purpose  : slot for setting the possibility to move nodes in viewer
378 //=================================================================================
379 void DependencyTree_View::onMoveNodes( bool theIsMoveNodes )
380 {
381   EntryObjectMap::const_iterator i;
382   for( i = myTreeMap.begin(); i != myTreeMap.end(); i++ ) {
383     DependencyTree_Object* object = myTreeMap[ i->first ];
384     if( object )
385       object->setMovable( theIsMoveNodes );
386   }
387 }
388
389 //=================================================================================
390 // function : onHierarchyType()
391 // purpose  : slot for setting the hierarchy type of tree
392 //=================================================================================
393 void DependencyTree_View::onHierarchyType()
394 {
395   myHierarchyDepth->setRange( 0, checkMaxLevelsNumber() );
396   if( myHierarchyDepth->value() > checkMaxLevelsNumber() )
397     myHierarchyDepth->setValue( checkMaxLevelsNumber() );
398
399   if( myHierarchyDepth->value() == 0 )
400     myLevelsNumber = myHierarchyDepth->maximum();
401   else
402     myLevelsNumber = myHierarchyDepth->value();
403
404   updateView();
405 }
406
407 //=================================================================================
408 // function : onPreferencesChanged()
409 // purpose  : slot for changing tree parameters from preferences
410 //=================================================================================
411 void DependencyTree_View::onPreferenceChanged( const QString& section, const QString& param )
412 {
413   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
414
415   if( param == QString("dependency_tree_hierarchy_type") ) {
416     int hierarchyType = resMgr->integerValue( section, param, 0);
417     setHierarchyType( hierarchyType );
418   }
419   else if(  param == QString("dependency_tree_move_nodes") ) {
420     bool isNodesMovable = resMgr->booleanValue( section, param, true);
421     setNodesMovable( isNodesMovable );
422   }
423   else if(  param == QString("dependency_tree_background_color") ) {
424     QColor c = resMgr->colorValue( section, param, QColor( 255, 255, 255 ) );
425     setPrefBackgroundColor( c );
426   }
427   else if(  param == QString("dependency_tree_node_color") ) {
428     QColor c = resMgr->colorValue( section, param, QColor( 62, 180, 238 ) );
429     setNodeColor( c );
430   }
431   else if(  param == QString("dependency_tree_main_node_color") ) {
432     QColor c = resMgr->colorValue( section, param, QColor( 238, 90, 125 ) );
433     setMainNodeColor( c );
434   }
435   else if(  param == QString("dependency_tree_unpublish_node_color") ) {
436     QColor c = resMgr->colorValue( section, param, QColor( 255, 255, 255 ) );
437     setUnpublishNodeColor( c );
438   }
439   else if(  param == QString("dependency_tree_select_node_color") ) {
440     QColor c = resMgr->colorValue( section, param, QColor( 237, 243, 58 ) );
441     setSelectNodeColor( c );
442   }
443   else if(  param == QString("dependency_tree_arrow_color") ) {
444     QColor c = resMgr->colorValue( section, param, QColor( 0, 0, 130 ) );
445     setArrowColor( c );
446   }
447   else if(  param == QString("dependency_tree_highlight_arrow_color") ) {
448     QColor c = resMgr->colorValue( section, param, QColor( 0, 0, 255 ) );
449     setHighlightArrowColor( c );
450   }
451   else if(  param == QString("dependency_tree_select_arrow_color") ) {
452     QColor c = resMgr->colorValue( section, param, QColor( 255, 0, 0 ) );
453     setSelectArrowColor( c );
454   }
455 }
456
457 //=================================================================================
458 // function : onRenameObject()
459 // purpose  : update object name, having edited it in Object Browser
460 //=================================================================================
461 void DependencyTree_View::onRenameObject( const QString& theEntry )
462 {
463   if( DependencyTree_Object* object = getObjectByEntry( theEntry.toStdString() ) )
464     object->updateName();
465 }
466
467 //=================================================================================
468 // function : parseTree()
469 // purpose  : parse created model to initialize all nodes and arrows
470 //=================================================================================
471 void DependencyTree_View::parseTree()
472 {
473   GEOMUtils::TreeModel::const_iterator i;
474   for( i = myTreeModel.begin(); i != myTreeModel.end(); i++ ) {
475     std::string objectEntry = i->first;
476     addNode( objectEntry );
477     parseTreeWard( i->second.first );
478     if( i->second.first.size() > myMaxUpwardLevelsNumber )
479       myMaxUpwardLevelsNumber = i->second.first.size();
480     parseTreeWard( i->second.second );
481     if( i->second.second.size() > myMaxDownwardLevelsNumber )
482       myMaxDownwardLevelsNumber = i->second.second.size();
483   }
484
485   for( i = myTreeModel.begin(); i != myTreeModel.end(); i++ ) {
486     DependencyTree_Object* Main_object = myTreeMap[ i->first ];
487     if( i->second.first.size() > 0 ) {
488       GEOMUtils::LevelInfo Levelup = i->second.first.at(0);
489       GEOMUtils::LevelInfo::const_iterator node;
490       for( node = Levelup.begin(); node != Levelup.end(); node++ ) {
491         DependencyTree_Object* object = myTreeMap[ node->first ];
492         addArrow( object, Main_object );
493       }
494     }
495     parseTreeWardArrow( i->second.first );
496     parseTreeWardArrow( i->second.second );
497   }
498 }
499
500 //=================================================================================
501 // function : parseTreeWard()
502 // purpose  : parse tree ward to initialize all nodes of current ward
503 //=================================================================================
504 void DependencyTree_View::parseTreeWard( const GEOMUtils::LevelsList& theWard )
505 {
506   int levelsNumber = theWard.size();
507   for( int level = 0; level < levelsNumber; level++ ) {
508     GEOMUtils::LevelInfo levelInfo = theWard[ level ];
509     GEOMUtils::LevelInfo::const_iterator node;
510     for( node = levelInfo.begin(); node != levelInfo.end(); node++ )
511       addNode( node->first );
512   }
513 }
514
515 //=================================================================================
516 // function : parseTreeWardArrow()
517 // purpose  : parse tree ward to initialize all arrows of current ward
518 //=================================================================================
519 void DependencyTree_View::parseTreeWardArrow( const GEOMUtils::LevelsList& theWard)
520 {
521   for( int j = 0; j < theWard.size(); j++ ) {
522     GEOMUtils::LevelInfo Level = theWard.at(j);
523     GEOMUtils::LevelInfo::const_iterator node;
524     for( node = Level.begin(); node != Level.end(); node++ ) {
525       DependencyTree_Object* object = myTreeMap[ node->first ];
526       std::vector<std::string> Links = node->second;
527       for( int link = 0; link < Links.size(); link++ ) {
528         DependencyTree_Object* LinkObject = myTreeMap[ Links[ link ] ];
529         if( object && LinkObject )
530           addArrow( LinkObject, object );
531       }
532     }
533   }
534 }
535
536 //=================================================================================
537 // function : addNode()
538 // purpose  : add node to viewer
539 //=================================================================================
540 void DependencyTree_View::addNode( const std::string& theEntry )
541 {
542   if( !myTreeMap[theEntry] )
543     myTreeMap[theEntry] = new DependencyTree_Object( theEntry );
544 }
545
546 //=================================================================================
547 // function : addArrow()
548 // purpose  : add arrow to viewer
549 //=================================================================================
550 void DependencyTree_View::addArrow( DependencyTree_Object* startItem, DependencyTree_Object* endItem )
551 {
552   bool isFind = false;
553
554   ArrowsInfo::const_iterator i;
555   for( i = myArrows.begin(); i != myArrows.end(); i++ ) {
556     DependencyTree_Arrow* arrow = i->second;
557     if( arrow->getStartItem() == startItem && arrow->getEndItem() == endItem )
558       isFind = true;
559     else if( arrow->getStartItem() == endItem && arrow->getEndItem() == startItem ) {
560       arrow->setIsBiLink( true );
561       isFind = true;
562     }
563   }
564   if( !isFind ) {
565     DependencyTree_Arrow *arrow = new DependencyTree_Arrow( startItem, endItem );
566     myArrows[ std::pair<DependencyTree_Object*,DependencyTree_Object*>( startItem, endItem ) ] = arrow;
567   }
568 }
569
570 //=================================================================================
571 // function : drawTree()
572 // purpose  : redraw dependency tree using existing model
573 //=================================================================================
574 void DependencyTree_View::drawTree()
575 {
576   clearView( false );
577   clearSelected();
578
579   // draw nodes on scene
580   std::map< std::string, int > entryLevelMap;
581   std::map< int, std::vector< std::string > > levelObjects;
582   int currentLevel;
583   int horDistance, verDistance;
584   GEOMUtils::TreeModel::const_reverse_iterator i;
585   for( i = myTreeModel.rbegin(); i != myTreeModel.rend(); i++ ) {
586     currentLevel = 0;
587     std::string objectEntry = i->first;
588     DependencyTree_Object* objectItem = myTreeMap[ objectEntry ];
589     horDistance = 100 + int( objectItem->boundingRect().width() );
590     verDistance = 3 * int( objectItem->boundingRect().height() );
591     if( isItemAdded( objectItem ) )
592       currentLevel = entryLevelMap[ objectEntry ];
593     else {
594       addItem( objectItem );
595       objectItem->unselect();
596       entryLevelMap[ objectEntry ] = currentLevel;
597       levelObjects[ currentLevel ].push_back( objectEntry );
598     }
599     objectItem->setIsMainObject( true );
600
601     if( myDisplayAscendants->isChecked() )
602       drawWard( i->second.first, entryLevelMap, levelObjects, currentLevel, -1 );
603     if( myDisplayDescendants->isChecked() )
604       drawWard( i->second.second, entryLevelMap, levelObjects, currentLevel, 1 );
605   }
606
607   std::map< int, std::vector< std::string > >::const_iterator level;
608   for( level = levelObjects.begin(); level != levelObjects.end(); level++ ) {
609     int step = -horDistance * ( int(level->second.size()) - 1 ) / 2;
610     for( int objIter = 0; objIter < level->second.size(); objIter++ ) {
611       DependencyTree_Object* anObject = myTreeMap[ level->second.at( objIter ) ];
612       anObject->setPos( step, verDistance * level->first );
613       step += horDistance;
614     }
615   }
616
617   // draw arrows on scene
618   GEOMUtils::TreeModel::const_iterator j;
619   for( j = myTreeModel.begin(); j != myTreeModel.end(); j++ ) {
620     DependencyTree_Object* Main_object = myTreeMap[ j->first ];
621     if( j->second.first.size() > 0 ) {
622       GEOMUtils::LevelInfo Levelup = j->second.first.at(0);
623       if( myDisplayAscendants ->isChecked() ) {
624         GEOMUtils::LevelInfo::const_iterator node;
625         for( node = Levelup.begin(); node != Levelup.end(); node++ ) {
626           DependencyTree_Object* object = myTreeMap[ node->first ];
627           DependencyTree_Arrow* arrow =
628             myArrows[ std::pair<DependencyTree_Object*,DependencyTree_Object*>( object, Main_object )];
629           if( arrow && !isItemAdded( arrow ) )
630             addItem( arrow );
631         }
632       }
633     }
634     if( myDisplayAscendants->isChecked() )
635       drawWardArrows( j->second.first );
636     if( myDisplayDescendants->isChecked() )
637       drawWardArrows( j->second.second );
638   }
639 }
640
641 //=================================================================================
642 // function : drawWard()
643 // purpose  : draw nodes of dependency tree ward (ascendant or descendant)
644 //=================================================================================
645 void DependencyTree_View::drawWard( const GEOMUtils::LevelsList& theWard,
646                                     std::map< std::string, int >& theEntryLevelMap,
647                                     std::map< int, std::vector< std::string > >& theLevelObjects,
648                                     int theCurrentLevel, const int theLevelStep )
649 {
650   for( int level = 0; level < theWard.size(); level++ ) {
651     if( level >= myLevelsNumber )
652       return;
653     theCurrentLevel += theLevelStep;
654     GEOMUtils::LevelInfo levelInfo = theWard.at( level );
655     GEOMUtils::LevelInfo::const_iterator node;
656     for( node = levelInfo.begin(); node != levelInfo.end(); node++ ) {
657       DependencyTree_Object* object = myTreeMap[ node->first ];
658       if( object && !isItemAdded( object ) ) {
659         addItem( object );
660         object->unselect();
661         theEntryLevelMap[ node->first ] = theCurrentLevel;
662         theLevelObjects[ theCurrentLevel ].push_back( node->first );
663       }
664     }
665   }
666 }
667
668 //=================================================================================
669 // function : drawWardArrows()
670 // purpose  : draw arrows of dependency tree ward (ascendant or descendant)
671 //=================================================================================
672 void DependencyTree_View::drawWardArrows( const GEOMUtils::LevelsList& theWard )
673 {
674   for( int j = 0; j < theWard.size(); j++ ) {
675     if( j >= myLevelsNumber )
676       break;
677     GEOMUtils::LevelInfo Level = theWard.at(j);
678     GEOMUtils::LevelInfo::const_iterator node;
679     for( node = Level.begin(); node != Level.end(); node++ ) {
680       DependencyTree_Object* object = myTreeMap[ node->first ];
681       GEOMUtils::NodeLinks Links = node->second;
682       for( int link = 0; link < Links.size(); link++ ) {
683         DependencyTree_Object* LinkObject = myTreeMap[ Links[ link ] ];
684         if( isItemAdded( object ) && isItemAdded( LinkObject ) ) {
685           DependencyTree_Arrow* arrow = myArrows[ std::pair<DependencyTree_Object*,DependencyTree_Object*>( LinkObject, object ) ];
686           if( arrow && !isItemAdded( arrow ) )
687             addItem( arrow );
688         }
689       }
690     }
691   }
692 }
693
694 //=================================================================================
695 // function : updateView()
696 // purpose  : update viewer using created dependency tree model
697 //=================================================================================
698 void DependencyTree_View::updateView()
699 {
700   if( !myIsUpdate )
701     return;
702
703   drawTree();
704   fitWindow();
705 }
706
707 //=================================================================================
708 // function : clearView()
709 // purpose  : clear viewer and initialize all variables
710 //=================================================================================
711 void DependencyTree_View::clearView( bool isClearModel )
712 {
713   EntryObjectMap::const_iterator objectIter;
714   for( objectIter = myTreeMap.begin(); objectIter != myTreeMap.end(); objectIter++ ) {
715     if( DependencyTree_Object* object = objectIter->second )
716       if( isItemAdded( object ) )
717         removeItem( object );
718   }
719
720   ArrowsInfo::const_iterator arrowIter;
721   for( arrowIter = myArrows.begin(); arrowIter != myArrows.end(); arrowIter++ ) {
722     if( DependencyTree_Arrow* arrow = arrowIter->second )
723       if( isItemAdded( arrow ) )
724         removeItem( arrow );
725   }
726
727   if( isClearModel ) {
728     EntryObjectMap::const_iterator objectIter;
729     for( objectIter = myTreeMap.begin(); objectIter != myTreeMap.end(); objectIter++ ) {
730       if( DependencyTree_Object* object = objectIter->second )
731         delete object;
732     }
733
734     ArrowsInfo::const_iterator arrowIter;
735     for( arrowIter = myArrows.begin(); arrowIter != myArrows.end(); arrowIter++ ) {
736       if( DependencyTree_Arrow* arrow = arrowIter->second )
737         delete arrow;
738     }
739     myTreeMap.clear();
740     myArrows.clear();
741     myTreeModel.clear();
742     myLevelsNumber = 0;
743     myMaxDownwardLevelsNumber = 0;
744     myMaxUpwardLevelsNumber = 0;
745     myIsUpdate = true;
746   }
747 }
748
749 //=================================================================================
750 // function : fitWindow()
751 // purpose  : scale the window considering a size of scene
752 //=================================================================================
753 void DependencyTree_View::fitWindow()
754 {
755   int sizeFactor = 4;
756   if( objectsBoundingRect(true).width() > sizeFactor*size().width() ||
757       objectsBoundingRect(true).height() > sizeFactor*size().width() ) {
758     QRectF aRect = QRectF( -sizeFactor*size().width()/2, -sizeFactor*size().height()/2,
759                            sizeFactor*size().width(), sizeFactor*size().height() );
760     fitInView( aRect, Qt::KeepAspectRatio );
761   }
762   else
763     fitAll();
764 }
765
766 //=================================================================================
767 // function : getNewTreeModel()
768 // purpose  : get dependency tree model from engine
769 //=================================================================================
770 void DependencyTree_View::getNewTreeModel( bool theUseSelectedObject, bool theUseOB )
771 {
772   GEOM::string_array_var objectsEntry = new GEOM::string_array();
773   int iter = 0;
774
775   if( theUseSelectedObject ) {
776     if( theUseOB ) {
777       SALOME_ListIO mainObjects;
778       mySelectionMgr->selectedObjects( mainObjects );
779       // create a list of selected object entry
780       objectsEntry->length( mainObjects.Extent() );
781       for ( SALOME_ListIteratorOfListIO It( mainObjects ); It.More(); It.Next(), iter++ ) {
782         Handle( SALOME_InteractiveObject ) io = It.Value();
783         if( !io->hasEntry() )
784           continue;
785         GEOM::GEOM_Object_var geomObject = GEOM::GEOM_Object::_nil();
786         geomObject = GEOMBase::ConvertIOinGEOMObject( io );
787         QString entry = geomObject->GetEntry();
788         objectsEntry[ iter ] = entry.toLatin1().constData();
789       }
790     }
791     else {
792       objectsEntry->length( nbSelected() );
793       for( initSelected(); moreSelected(); nextSelected(), iter++ )
794         if( DependencyTree_Object* treeObject = dynamic_cast<DependencyTree_Object*>( selectedObject() ) )
795           objectsEntry[ iter ] = treeObject->getEntry().c_str();
796     }
797     myMainEntries = objectsEntry;
798   }
799
800   // get string which describes dependency tree structure
801   SALOMEDS::TMPFile_var SeqFile =
802     GeometryGUI::GetGeomGen()->GetDependencyTree( myStudy, myMainEntries );
803   char* buf = (char*)&SeqFile[0];
804
805   clearView( true );
806   mySelectionMgr->clearSelected();
807
808   // get dependency tree structure
809   GEOMUtils::ConvertStringToTree( buf, myTreeModel );
810
811   parseTree();
812 }
813
814 //=================================================================================
815 // function : checkMaxLevelsNumber()
816 // purpose  : calculate max levels number
817 //=================================================================================
818 int DependencyTree_View::checkMaxLevelsNumber()
819 {
820   if( myDisplayAscendants->isChecked() && myDisplayDescendants->isChecked() )
821     return myMaxUpwardLevelsNumber > myMaxDownwardLevelsNumber ?
822            myMaxUpwardLevelsNumber : myMaxDownwardLevelsNumber;
823   else if( myDisplayAscendants ->isChecked() )
824     return myMaxUpwardLevelsNumber;
825   else if( myDisplayDescendants->isChecked() )
826     return  myMaxDownwardLevelsNumber;
827 }