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