Salome HOME
Fix regressions
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_SelectionOp.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File   : SMESHGUI_SelectionOp.cxx
24 // Author : Alexander SOLOVYOV, Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_SelectionOp.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_VTKUtils.h"
31 #include "SMESHGUI_MeshUtils.h"
32 #include "SMESHGUI_Selection.h"
33
34 #include <SMESH_Actor.h>
35 #include <SMDS_Mesh.hxx>
36 #include <SMDS_MeshNode.hxx>
37
38 // SALOME GUI includes
39 #include <SUIT_SelectionFilter.h>
40 #include <LightApp_SelectionMgr.h>
41 #include <SalomeApp_Study.h>
42 #include <SVTK_ViewWindow.h>
43 #include <SVTK_ViewModel.h>
44
45 #include <SALOME_ListIO.hxx>
46
47 // SALOME KERNEL includes 
48 #include <SALOMEDS_SObject.hxx>
49
50 /*
51   Class       : SMESHGUI_SelectionOp
52   Description : Base operation for all operations using object selection in viewer or objectbrowser
53                 through common widgets created by LightApp_Dialog::createObject
54 */
55
56 //=================================================================================
57 // name     : SMESHGUI_SelectionOp
58 // purpose  : 
59 //=================================================================================
60 SMESHGUI_SelectionOp::SMESHGUI_SelectionOp( const Selection_Mode mode )
61 : SMESHGUI_Operation(),
62   myDefSelectionMode( mode )
63 {
64 }
65
66 //=================================================================================
67 // name     : ~SMESHGUI_SelectionOp
68 // purpose  :
69 //=================================================================================
70 SMESHGUI_SelectionOp::~SMESHGUI_SelectionOp()
71 {
72   removeCustomFilters();
73 }
74
75 //=================================================================================
76 // name     : startOperation
77 // purpose  :
78 //=================================================================================
79 void SMESHGUI_SelectionOp::startOperation()
80 {
81   myOldSelectionMode = selectionMode();
82   setSelectionMode( myDefSelectionMode );
83
84   SMESHGUI_Operation::startOperation();
85   if( dlg() )
86   {
87     disconnect( dlg(), SIGNAL( objectActivated( int ) ), this, SLOT( onActivateObject( int ) ) );
88     disconnect( dlg(), SIGNAL( objectDeactivated( int ) ), this, SLOT( onDeactivateObject( int ) ) );
89     disconnect( dlg(), SIGNAL( selectionChanged( int ) ), this, SLOT( onSelectionChanged( int ) ) );
90     connect( dlg(), SIGNAL( objectActivated( int ) ), this, SLOT( onActivateObject( int ) ) );
91     connect( dlg(), SIGNAL( objectDeactivated( int ) ), this, SLOT( onDeactivateObject( int ) ) );
92     connect( dlg(), SIGNAL( selectionChanged( int ) ), this, SLOT( onSelectionChanged( int ) ) );
93   }
94 }
95
96 //=================================================================================
97 // name     : removeCustomFilters
98 // purpose  :
99 //=================================================================================
100 void SMESHGUI_SelectionOp::removeCustomFilters()
101 {
102   if (myFilters.count() > 0) {
103     LightApp_SelectionMgr* mgr = selectionMgr();
104     Filters::const_iterator anIt = myFilters.begin(),
105                             aLast = myFilters.end();
106     for ( ; anIt != aLast; anIt++) {
107       if (anIt.value()) {
108         if (mgr) mgr->removeFilter(anIt.value());
109         delete anIt.value();
110       }
111     }
112
113     myFilters.clear();
114   }
115 }
116
117 //=================================================================================
118 // name     : commitOperation
119 // purpose  :
120 //=================================================================================
121 void SMESHGUI_SelectionOp::commitOperation()
122 {
123   SMESHGUI_Operation::commitOperation();  
124   removeCustomFilters();
125   setSelectionMode( myOldSelectionMode );
126 }
127
128 //=================================================================================
129 // name     : abortOperation
130 // purpose  :
131 //=================================================================================
132 void SMESHGUI_SelectionOp::abortOperation()
133 {
134   SMESHGUI_Operation::abortOperation();
135   removeCustomFilters();
136   setSelectionMode( myOldSelectionMode );  
137 }
138
139 //=================================================================================
140 // name     : selectionDone
141 // purpose  :
142 //=================================================================================
143 void SMESHGUI_SelectionOp::selectionDone()
144 {
145   if( !dlg() )
146     return;
147
148   if( selectionMode()!=ActorSelection )
149   {
150     SALOME_ListIO aList;
151     selectionMgr()->selectedObjects( aList, SVTK_Viewer::Type() );
152
153     if( aList.Extent() != 1 ) //we can select nodes or elements only within one mesh
154     {
155       dlg()->clearSelection();
156       return;
157     }    
158   }
159     
160   QStringList names, ids;
161   LightApp_Dialog::TypesList types;
162   selected( names, types, ids );
163   dlg()->selectObject( names, types, ids );
164 }
165
166 //=================================================================================
167 // name     : createFilter
168 // purpose  :
169 //=================================================================================
170 SUIT_SelectionFilter* SMESHGUI_SelectionOp::createFilter( const int ) const
171 {
172   return 0;
173 }
174
175 //=================================================================================
176 // name     : onActivateObject
177 // purpose  :
178 //=================================================================================
179 void SMESHGUI_SelectionOp::onActivateObject( int id )
180 {
181   LightApp_SelectionMgr* mgr = selectionMgr();
182   if( !mgr )
183     return;
184     
185   if( !myFilters.contains( id ) )
186     myFilters[ id ] = createFilter( id );
187
188   if( myFilters[ id ] )
189     mgr->installFilter( myFilters[ id ] );
190
191   selectionDone();
192 }
193
194 //=================================================================================
195 // name     : onDeactivateObject
196 // purpose  :
197 //=================================================================================
198 void SMESHGUI_SelectionOp::onDeactivateObject( int id )
199 {
200   removeCustomFilters();
201 }
202
203 //=================================================================================
204 // name     : initDialog
205 // purpose  :
206 //=================================================================================
207 void SMESHGUI_SelectionOp::initDialog()
208 {
209   if( dlg() )
210   {
211     dlg()->clearSelection();
212     dlg()->deactivateAll();
213   }
214 }
215
216 //=================================================================================
217 // name     : initDialog
218 // purpose  :
219 //=================================================================================
220 void SMESHGUI_SelectionOp::onSelectionChanged( int )
221 {
222 }
223
224 //=======================================================================
225 // name    : selectionMode
226 // Purpose : Returns selection mode
227 //=======================================================================
228 Selection_Mode SMESHGUI_SelectionOp::selectionMode() const
229 {
230   SVTK_ViewWindow* wnd = viewWindow();
231   if( wnd )
232     return wnd->SelectionMode();
233   else
234     return ActorSelection;
235 }
236
237 //=======================================================================
238 // name    : setSelectionMode
239 // Purpose : Set selection mode
240 //=======================================================================
241 void SMESHGUI_SelectionOp::setSelectionMode( const Selection_Mode mode )
242 {
243   SVTK_ViewWindow* wnd = viewWindow();
244   if( wnd )
245     wnd->SetSelectionMode( mode );
246 }
247
248 //=======================================================================
249 // name    : highlight
250 // Purpose : Highlight object in 3d viewer
251 //=======================================================================
252 void SMESHGUI_SelectionOp::highlight( const Handle( SALOME_InteractiveObject )& obj,
253                                       const bool hilight, const bool immediately )
254 {
255   SVTK_ViewWindow* wnd = viewWindow();
256   if( wnd )
257     wnd->highlight( obj, hilight, immediately );
258 }
259
260 //=======================================================================
261 // name    : addOrRemoveIndex
262 // Purpose : Select/deselect cells of mesh
263 //=======================================================================
264 void SMESHGUI_SelectionOp::addOrRemoveIndex( const Handle( SALOME_InteractiveObject )& obj,
265                                              const TColStd_MapOfInteger& indices,
266                                              const bool isModeShift )
267 {
268   SVTK_Selector* sel = selector();
269   if( sel )
270     sel->AddOrRemoveIndex( obj, indices, isModeShift );
271 }
272
273 //=======================================================================
274 // name    : viewWindow
275 // Purpose : Get active view window
276 //=======================================================================
277 SVTK_ViewWindow* SMESHGUI_SelectionOp::viewWindow() const
278 {
279   return SMESH::GetViewWindow( getSMESHGUI() );
280 }
281
282 //=======================================================================
283 // name    : selector
284 // Purpose : Get selector
285 //=======================================================================
286 SVTK_Selector* SMESHGUI_SelectionOp::selector() const
287 {
288   SVTK_ViewWindow* wnd = viewWindow();
289   return wnd ? wnd->GetSelector() : 0;
290 }
291
292 //=======================================================================
293 // name    : typeById
294 // Purpose : Find type by id
295 //=======================================================================
296 int SMESHGUI_SelectionOp::typeById( const QString& str, const EntityType objtype ) const
297 {
298   SalomeApp_Study* _study = dynamic_cast<SalomeApp_Study*>( study() );
299   if( !_study )
300     return -1;
301
302   _PTR( Study ) st = _study->studyDS();
303
304   int res = -1;
305   if( objtype == Object )
306   {
307     SalomeApp_Study* _study = dynamic_cast<SalomeApp_Study*>( study() );
308     if( _study )
309     {
310       int t = SMESHGUI_Selection::type( str, _study->studyDS() );
311       if( t<0 )
312       {
313         //try to get GEOM type
314         _PTR( SObject ) sobj = st->FindObjectID( str.toLatin1().data() );
315         if( sobj )
316         {
317           GEOM::GEOM_Object_var obj = GEOM::GEOM_Object::_narrow(
318             dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
319           if( !CORBA::is_nil( obj ) )
320             // as decoding of type id is not realized in LightApp_Dialog,
321             //make all GEOM objects have same type id
322             res = SMESHGUI_Dialog::prefix( "GEOM" );// + obj->GetType();
323         }
324       }
325       else
326         res = SMESHGUI_Dialog::prefix( "SMESH" ) + t;
327     }
328   }
329   else
330   {
331     int pos = str.indexOf( idChar() );
332     QString entry = str.left( pos ),
333             _id = str.mid( pos+1 );
334     bool ok;
335     int id = _id.toInt( &ok );
336     if( ok )
337     {
338       _PTR( SObject ) sobj = st->FindObjectID( entry.toLatin1().data() );
339       SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( 
340         dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
341       SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( 
342         dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
343       if( !CORBA::is_nil( mesh ) )
344         res = SMESHGUI_Dialog::prefix( "SMESH element" ) + 
345           mesh->GetElementType( id, objtype==MeshElement );
346
347       else if( !CORBA::is_nil( submesh ) )
348         res = SMESHGUI_Dialog::prefix( "SMESH element" ) + 
349           submesh->GetElementType( id, objtype==MeshElement );
350     }
351   }
352
353   return res;
354 }
355
356 //=======================================================================
357 // name    : selected
358 // Purpose : Get names, types and ids of selected objects
359 //=======================================================================
360 void SMESHGUI_SelectionOp::selected( QStringList& names,
361                                      LightApp_Dialog::TypesList& types,
362                                      QStringList& ids ) const
363 {
364 /*  SUIT_DataOwnerPtrList list; selectionMgr()->selected( list );
365   SUIT_DataOwnerPtrList::const_iterator anIt = list.begin(),
366                                         aLast = list.end();
367   for( ; anIt!=aLast; anIt++ )
368   {
369     LightApp_DataOwner* owner = dynamic_cast<LightApp_DataOwner*>( (*anIt).operator->() );
370     LightApp_SVTKDataOwner* vtkowner = dynamic_cast<LightApp_SVTKDataOwner*>( (*anIt).operator->() );
371
372     if( vtkowner )
373     {
374       QString id_str = QString( "%1%2%3" ).arg( vtkowner->entry() ).arg( idChar() ), current_id_str;
375       Selection_Mode mode = vtkowner->GetMode();
376       EntityType objtype = mode == NodeSelection ? MeshNode : MeshElement;
377       const TColStd_IndexedMapOfInteger& ownerids = vtkowner->GetIds();
378
379       for( int i=1, n=ownerids.Extent(); i<=n; i++ )
380       {
381         int curid = ownerids( i );
382         current_id_str = id_str.arg( curid );
383         ids.append( current_id_str );
384         types.append( typeById( current_id_str, objtype ) );
385         names.append( QString( "%1" ).arg( curid ) );
386       }
387     }
388
389     else if( owner )
390     {
391       QString id = owner->entry();
392       ids.append( id );
393       types.append( typeById( id, Object ) );
394       names.append( owner->IO()->getName() );
395     }
396   }*/
397
398   SALOME_ListIO selObjs;
399   TColStd_IndexedMapOfInteger selIndices;
400   selectionMgr()->selectedObjects( selObjs );
401   Selection_Mode mode = selectionMode();
402   EntityType objtype = mode == NodeSelection ? MeshNode : MeshElement;
403
404   for( SALOME_ListIteratorOfListIO anIt( selObjs ); anIt.More(); anIt.Next() )
405   {
406     selIndices.Clear();
407     selectionMgr()->GetIndexes( anIt.Value(), selIndices );
408     if( selIndices.Extent() > 0 )
409     {
410       QString id_str = QString( "%1%2%3" ).arg( anIt.Value()->getEntry() ).arg( idChar() ), current_id_str;
411       for( int i=1, n=selIndices.Extent(); i<=n; i++ )
412       {
413         int curid = selIndices( i );
414         current_id_str = id_str.arg( curid );
415         ids.append( current_id_str );
416         types.append( typeById( current_id_str, objtype ) );
417         names.append( QString( "%1" ).arg( curid ) );
418       }
419     }
420     else
421     {
422       QString id = anIt.Value()->getEntry();
423       ids.append( id );
424       types.append( typeById( id, Object ) );
425       SalomeApp_Study* _study = dynamic_cast<SalomeApp_Study*>( study() );
426       if( _study )
427       {
428         _PTR(SObject) obj = _study->studyDS()->FindObjectID( anIt.Value()->getEntry() );
429         if( obj )
430           names.append( QString( obj->GetName().c_str() ).trimmed() );
431       }
432     }
433   }
434 }
435
436 //=======================================================================
437 // name    : idChar
438 // Purpose : Char using to divide <entry> and <id> in string id representation. By default, '#'
439 //=======================================================================
440 QChar SMESHGUI_SelectionOp::idChar() const
441 {
442   return '#';
443 }
444
445 //=================================================================================
446 // name     : mesh
447 // purpose  :
448 //=================================================================================
449 SMESH::SMESH_Mesh_var SMESHGUI_SelectionOp::mesh() const
450 {
451   if( selectionMode()==ActorSelection )
452     return SMESH::SMESH_Mesh::_nil();
453     
454   SALOME_ListIO sel; selectionMgr()->selectedObjects( sel, SVTK_Viewer::Type() );
455   if( sel.Extent()==1 )
456     return SMESH::GetMeshByIO( sel.First() );
457   else
458     return SMESH::SMESH_Mesh::_nil();
459 }
460
461 //=================================================================================
462 // name     : actor
463 // purpose  :
464 //=================================================================================
465 SMESH_Actor* SMESHGUI_SelectionOp::actor() const
466 {
467   SMESH::SMESH_Mesh_var m = mesh();
468   if( !m->_is_nil() )
469     return SMESH::FindActorByObject( m.in() );
470   else
471     return 0;
472 }
473
474 //=================================================================================
475 // name     : onTextChanged
476 // purpose  :
477 //=================================================================================
478 void SMESHGUI_SelectionOp::onTextChanged( int, const QStringList& list )
479 {
480     if( !dlg() )
481       return;
482
483     TColStd_MapOfInteger newIndices;
484
485     SALOME_ListIO sel; selectionMgr()->selectedObjects( sel );
486     SMESH_Actor* anActor = actor();
487     if( sel.Extent()==0 || !anActor )
488       return;
489
490     SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
491
492     IdList ids; extractIds( list, ids, '\0' );
493     IdList::const_iterator anIt = ids.begin(),
494                            aLast = ids.end();
495     if ( selectionMode() == NodeSelection )
496       for( ; anIt!=aLast; anIt++ ) {
497         if( const SMDS_MeshNode * n = aMesh->FindNode( *anIt ) )
498           newIndices.Add( n->GetID() );
499       }
500     else 
501       for( ; anIt!=aLast; anIt++ ) {
502         if( const SMDS_MeshElement* e = aMesh->FindElement( *anIt ) )
503           newIndices.Add( e->GetID() );
504       }
505
506     selector()->AddOrRemoveIndex( sel.First(), newIndices, false );
507     highlight( sel.First(), true, true );
508
509     QStringList names, _ids; LightApp_Dialog::TypesList types;
510     selected( names, types, _ids );
511     dlg()->selectObject( names, types, _ids, false );
512 }
513
514 //=================================================================================
515 // name     : selectedIds
516 // purpose  :
517 //=================================================================================
518 void SMESHGUI_SelectionOp::selectedIds( const int id, IdList& list ) const
519 {
520   if( !dlg() )
521     return;
522
523   QStringList ids; dlg()->selectedObject( id, ids );
524   extractIds( ids, list );
525 }
526
527 //=================================================================================
528 // name     : extractIds
529 // purpose  :
530 //=================================================================================
531 void SMESHGUI_SelectionOp::extractIds( const QStringList& ids, IdList& list, const QChar idchar )
532 {
533   QStringList::const_iterator anIt = ids.begin(),
534                               aLast = ids.end();
535   QString id_str;
536   for( ; anIt!=aLast; anIt++ )
537   {
538     id_str = *anIt;
539     int pos = idchar=='\0' ? -1 : id_str.indexOf( idchar );
540     int id = -1;
541     if( idchar=='\0' || pos>=0 )
542     {
543       id = id_str.mid( pos+1 ).toInt();
544       list.append( id );
545     }
546   }
547 }
548
549 //=================================================================================
550 // name     : extractIds
551 // purpose  :
552 //=================================================================================
553 void SMESHGUI_SelectionOp::extractIds( const QStringList& ids, IdList& list ) const
554 {
555   extractIds( ids, list, idChar() );
556 }