Salome HOME
0022379: EDF 2276 GEOM: Dependency Tree - reverse the direction of the arrows
[modules/geom.git] / src / DependencyTree / DependencyTree_View.cxx
1 // Copyright (C) 2014  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 : 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( i->second.first.size() > myMaxUpwardLevelsNumber )
467       myMaxUpwardLevelsNumber = i->second.first.size();
468     parseTreeWard( i->second.second );
469     if( 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( int 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( int 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( int 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; level < theWard.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; j < theWard.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( int 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   fitAll();
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 : getNewTreeModel()
739 // purpose  : get dependency tree model from engine
740 //=================================================================================
741 void DependencyTree_View::getNewTreeModel( bool theUseSelectedObject, bool theUseOB )
742 {
743   GEOM::string_array_var objectsEntry = new GEOM::string_array();
744   int iter = 0;
745
746   if( theUseSelectedObject ) {
747     if( theUseOB ) {
748       SALOME_ListIO mainObjects;
749       mySelectionMgr->selectedObjects( mainObjects );
750       // create a list of selected object entry
751       objectsEntry->length( mainObjects.Extent() );
752       for ( SALOME_ListIteratorOfListIO It( mainObjects ); It.More(); It.Next(), iter++ ) {
753         Handle( SALOME_InteractiveObject ) io = It.Value();
754         if( !io->hasEntry() )
755           continue;
756         GEOM::GEOM_Object_var geomObject = GEOM::GEOM_Object::_nil();
757         geomObject = GEOMBase::ConvertIOinGEOMObject( io );
758         QString entry = geomObject->GetEntry();
759         objectsEntry[ iter ] = entry.toLatin1().constData();
760       }
761     }
762     else {
763       objectsEntry->length( nbSelected() );
764       for( initSelected(); moreSelected(); nextSelected(), iter++ )
765         if( DependencyTree_Object* treeObject = dynamic_cast<DependencyTree_Object*>( selectedObject() ) )
766           objectsEntry[ iter ] = treeObject->getEntry().c_str();
767     }
768     myMainEntries = objectsEntry;
769   }
770
771   // get string which describes dependency tree structure
772   SALOMEDS::TMPFile_var SeqFile =
773     GeometryGUI::GetGeomGen()->GetDependencyTree( myStudy, myMainEntries );
774   char* buf = (char*)&SeqFile[0];
775
776   clearView( true );
777   mySelectionMgr->clearSelected();
778
779   // get dependency tree structure
780   GEOMUtils::ConvertStringToTree( buf, myTreeModel );
781
782   parseTree();
783 }
784
785 //=================================================================================
786 // function : checkMaxLevelsNumber()
787 // purpose  : calculate max levels number
788 //=================================================================================
789 int DependencyTree_View::checkMaxLevelsNumber()
790 {
791   if( myDisplayAscendants->isChecked() && myDisplayDescendants->isChecked() )
792     return myMaxUpwardLevelsNumber > myMaxDownwardLevelsNumber ?
793            myMaxUpwardLevelsNumber : myMaxDownwardLevelsNumber;
794   else if( myDisplayAscendants ->isChecked() )
795     return myMaxUpwardLevelsNumber;
796   else if( myDisplayDescendants->isChecked() )
797     return  myMaxDownwardLevelsNumber;
798 }