Salome HOME
6992319581dfa5c7bfbf82eb7c29229d10160c5e
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_SelectionOp.cxx
1 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
3 // 
4 //  This library is free software; you can redistribute it and/or 
5 //  modify it under the terms of the GNU Lesser General Public 
6 //  License as published by the Free Software Foundation; either 
7 //  version 2.1 of the License. 
8 // 
9 //  This library is distributed in the hope that it will be useful, 
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 //  Lesser General Public License for more details. 
13 // 
14 //  You should have received a copy of the GNU Lesser General Public 
15 //  License along with this library; if not, write to the Free Software 
16 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
17 // 
18 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
19 //
20 //
21 //
22 //  File   : SMESHGUI_SelectionOp.cxx
23 //  Author : Alexander SOLOVYOV
24 //  Module : SMESH
25
26 #include <SMESHGUI_SelectionOp.h>
27 #include <SMESHGUI_VTKUtils.h>
28 #include <SMESHGUI_MeshUtils.h>
29 #include <SMESHGUI_Selection.h>
30 #include <SMESHGUI.h>
31 #include <SUIT_SelectionFilter.h>
32 #include <SalomeApp_SelectionMgr.h>
33 #include <SalomeApp_Study.h>
34 #include <SalomeApp_VTKSelector.h>
35 #include <SVTK_ViewWindow.h>
36 #include <SVTK_ViewModel.h>
37 #include <SVTK_Selector.h>
38 #include <SMESH_Actor.h>
39
40 #include <SMDS_Mesh.hxx>
41 #include <SMDS_MeshNode.hxx>
42
43 #include CORBA_SERVER_HEADER(GEOM_Gen)
44 #include <SALOMEDS_SObject.hxx>
45
46 #include <SALOME_ListIteratorOfListIO.hxx>
47
48 /*
49   Class       : SMESHGUI_SelectionOp
50   Description : Base operation for all operations using object selection in viewer or objectbrowser
51                 through common widgets created by SalomeApp_Dialog::createObject
52 */
53
54 //=================================================================================
55 // name     : SMESHGUI_SelectionOp
56 // purpose  : 
57 //=================================================================================
58 SMESHGUI_SelectionOp::SMESHGUI_SelectionOp( const Selection_Mode mode )
59 : SMESHGUI_Operation(),
60   myDefSelectionMode( mode )
61 {
62 }
63
64 //=================================================================================
65 // name     : ~SMESHGUI_SelectionOp
66 // purpose  :
67 //=================================================================================
68 SMESHGUI_SelectionOp::~SMESHGUI_SelectionOp()
69 {
70   Filters::const_iterator anIt = myFilters.begin(),
71                           aLast = myFilters.end();
72   for( ; anIt!=aLast; anIt++ )
73     if( anIt.data() )
74       delete anIt.data();
75 }
76
77 //=================================================================================
78 // name     : startOperation
79 // purpose  :
80 //=================================================================================
81 void SMESHGUI_SelectionOp::startOperation()
82 {
83   SMESHGUI_Operation::startOperation();
84   if( dlg() )
85   {
86     disconnect( dlg(), SIGNAL( objectActivated( int ) ), this, SLOT( onActivateObject( int ) ) );
87     disconnect( dlg(), SIGNAL( objectDeactivated( int ) ), this, SLOT( onDeactivateObject( int ) ) );
88     disconnect( dlg(), SIGNAL( selectionChanged( int ) ), this, SLOT( onSelectionChanged( int ) ) );
89     connect( dlg(), SIGNAL( objectActivated( int ) ), this, SLOT( onActivateObject( int ) ) );
90     connect( dlg(), SIGNAL( objectDeactivated( int ) ), this, SLOT( onDeactivateObject( int ) ) );
91     connect( dlg(), SIGNAL( selectionChanged( int ) ), this, SLOT( onSelectionChanged( int ) ) );
92   }
93
94   myOldSelectionMode = selectionMode();
95   setSelectionMode( myDefSelectionMode );
96 }
97
98 //=================================================================================
99 // name     : removeCustomFilters
100 // purpose  :
101 //=================================================================================
102 void SMESHGUI_SelectionOp::removeCustomFilters() const
103 {
104   SalomeApp_SelectionMgr* mgr = selectionMgr();
105   if( !mgr )
106     return;
107     
108   Filters::const_iterator anIt = myFilters.begin(),
109                           aLast = myFilters.end();
110   for( ; anIt!=aLast; anIt++ )
111     if( anIt.data() )
112       mgr->removeFilter( anIt.data() );
113 }
114
115 //=================================================================================
116 // name     : commitOperation
117 // purpose  :
118 //=================================================================================
119 void SMESHGUI_SelectionOp::commitOperation()
120 {
121   removeCustomFilters();
122   setSelectionMode( myOldSelectionMode );
123   SMESHGUI_Operation::commitOperation();  
124 }
125
126 //=================================================================================
127 // name     : abortOperation
128 // purpose  :
129 //=================================================================================
130 void SMESHGUI_SelectionOp::abortOperation()
131 {
132   removeCustomFilters();
133   setSelectionMode( myOldSelectionMode );  
134   SMESHGUI_Operation::abortOperation();
135 }
136
137 //=================================================================================
138 // name     : selectionDone
139 // purpose  :
140 //=================================================================================
141 void SMESHGUI_SelectionOp::selectionDone()
142 {
143   if( !dlg() )
144     return;
145
146   if( selectionMode()!=ActorSelection )
147   {
148     SALOME_ListIO aList;
149     selectionMgr()->selectedObjects( aList, SVTK_Viewer::Type() );
150
151     if( aList.Extent() != 1 ) //we can select nodes or elements only within one mesh
152     {
153       dlg()->clearSelection();
154       return;
155     }    
156   }
157     
158   QStringList names, ids;
159   SalomeApp_Dialog::TypesList types;
160   selected( names, types, ids );
161   dlg()->selectObject( names, types, ids );
162 }
163
164 //=================================================================================
165 // name     : createFilter
166 // purpose  :
167 //=================================================================================
168 SUIT_SelectionFilter* SMESHGUI_SelectionOp::createFilter( const int ) const
169 {
170   return 0;
171 }
172
173 //=================================================================================
174 // name     : onActivateObject
175 // purpose  :
176 //=================================================================================
177 void SMESHGUI_SelectionOp::onActivateObject( int id )
178 {
179   SalomeApp_SelectionMgr* mgr = selectionMgr();
180   if( !mgr )
181     return;
182     
183   if( !myFilters.contains( id ) )
184     myFilters[ id ] = createFilter( id );
185
186   if( myFilters[ id ] )
187     mgr->installFilter( myFilters[ id ] );
188
189   selectionDone();
190 }
191
192 //=================================================================================
193 // name     : onDeactivateObject
194 // purpose  :
195 //=================================================================================
196 void SMESHGUI_SelectionOp::onDeactivateObject( int id )
197 {
198   SalomeApp_SelectionMgr* mgr = selectionMgr();
199   if( mgr && myFilters.contains( id ) && myFilters[ id ] )
200     mgr->removeFilter( myFilters[ id ] );
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.latin1() );
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             res = SMESHGUI_Dialog::prefix( "GEOM" ) + obj->GetType();
321         }
322       }
323       else
324         res = SMESHGUI_Dialog::prefix( "SMESH" ) + t;
325     }
326   }
327   else
328   {
329     int pos = str.find( idChar() );
330     QString entry = str.left( pos ),
331             _id = str.mid( pos+1 );
332     bool ok;
333     int id = _id.toInt( &ok );
334     if( ok )
335     {
336       _PTR( SObject ) sobj = st->FindObjectID( entry.latin1() );
337       SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( 
338         dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
339       SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( 
340         dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
341       if( !CORBA::is_nil( mesh ) )
342         res = SMESHGUI_Dialog::prefix( "SMESH element" ) + 
343           mesh->GetElementType( id, objtype==MeshElement );
344
345       else if( !CORBA::is_nil( submesh ) )
346         res = SMESHGUI_Dialog::prefix( "SMESH element" ) + 
347           submesh->GetElementType( id, objtype==MeshElement );
348     }
349   }
350
351   return res;
352 }
353
354 //=======================================================================
355 // name    : selected
356 // Purpose : Get names, types and ids of selected objects
357 //=======================================================================
358 void SMESHGUI_SelectionOp::selected( QStringList& names,
359                                      SalomeApp_Dialog::TypesList& types,
360                                      QStringList& ids ) const
361 {
362 /*  SUIT_DataOwnerPtrList list; selectionMgr()->selected( list );
363   SUIT_DataOwnerPtrList::const_iterator anIt = list.begin(),
364                                         aLast = list.end();
365   for( ; anIt!=aLast; anIt++ )
366   {
367     SalomeApp_DataOwner* owner = dynamic_cast<SalomeApp_DataOwner*>( (*anIt).operator->() );
368     SalomeApp_SVTKDataOwner* vtkowner = dynamic_cast<SalomeApp_SVTKDataOwner*>( (*anIt).operator->() );
369
370     if( vtkowner )
371     {
372       QString id_str = QString( "%1%2%3" ).arg( vtkowner->entry() ).arg( idChar() ), current_id_str;
373       Selection_Mode mode = vtkowner->GetMode();
374       EntityType objtype = mode == NodeSelection ? MeshNode : MeshElement;
375       const TColStd_IndexedMapOfInteger& ownerids = vtkowner->GetIds();
376
377       for( int i=1, n=ownerids.Extent(); i<=n; i++ )
378       {
379         int curid = ownerids( i );
380         current_id_str = id_str.arg( curid );
381         ids.append( current_id_str );
382         types.append( typeById( current_id_str, objtype ) );
383         names.append( QString( "%1" ).arg( curid ) );
384       }
385     }
386
387     else if( owner )
388     {
389       QString id = owner->entry();
390       ids.append( id );
391       types.append( typeById( id, Object ) );
392       names.append( owner->IO()->getName() );
393     }
394   }*/
395
396   SALOME_ListIO selObjs;
397   TColStd_IndexedMapOfInteger selIndices;
398   selectionMgr()->selectedObjects( selObjs );
399   Selection_Mode mode = selectionMode();
400   EntityType objtype = mode == NodeSelection ? MeshNode : MeshElement;
401
402   for( SALOME_ListIteratorOfListIO anIt( selObjs ); anIt.More(); anIt.Next() )
403   {
404     selIndices.Clear();
405     selectionMgr()->GetIndexes( anIt.Value(), selIndices );
406     if( selIndices.Extent()==0 )
407     {
408       QString id_str = QString( "%1%2%3" ).arg( anIt.Value()->getEntry() ).arg( idChar() ), current_id_str;
409       for( int i=1, n=selIndices.Extent(); i<=n; i++ )
410       {
411         int curid = selIndices( i );
412         current_id_str = id_str.arg( curid );
413         ids.append( current_id_str );
414         types.append( typeById( current_id_str, objtype ) );
415         names.append( QString( "%1" ).arg( curid ) );
416       }
417     }
418     else
419     {
420       QString id = anIt.Value()->getEntry();
421       ids.append( id );
422       types.append( typeById( id, Object ) );
423       names.append( anIt.Value()->getName() );
424     }
425   }
426 }
427
428 //=======================================================================
429 // name    : idChar
430 // Purpose : Char using to divide <entry> and <id> in string id representation. By default, '#'
431 //=======================================================================
432 QChar SMESHGUI_SelectionOp::idChar() const
433 {
434   return '#';
435 }
436
437 //=================================================================================
438 // name     : mesh
439 // purpose  :
440 //=================================================================================
441 SMESH::SMESH_Mesh_var SMESHGUI_SelectionOp::mesh() const
442 {
443   if( selectionMode()==ActorSelection )
444     return SMESH::SMESH_Mesh::_nil();
445     
446   SALOME_ListIO sel; selectionMgr()->selectedObjects( sel, SVTK_Viewer::Type() );
447   if( sel.Extent()==1 )
448     return SMESH::GetMeshByIO( sel.First() );
449   else
450     return SMESH::SMESH_Mesh::_nil();
451 }
452
453 //=================================================================================
454 // name     : actor
455 // purpose  :
456 //=================================================================================
457 SMESH_Actor* SMESHGUI_SelectionOp::actor() const
458 {
459   SMESH::SMESH_Mesh_var m = mesh();
460   if( !m->_is_nil() )
461     return SMESH::FindActorByObject( m.in() );
462   else
463     return 0;
464 }
465
466 //=================================================================================
467 // name     : onTextChanged
468 // purpose  :
469 //=================================================================================
470 void SMESHGUI_SelectionOp::onTextChanged( int, const QStringList& list )
471 {
472     if( !dlg() )
473       return;
474
475     TColStd_MapOfInteger newIndices;
476
477     SALOME_ListIO sel; selectionMgr()->selectedObjects( sel );
478     SMESH_Actor* anActor = actor();
479     if( sel.Extent()==0 || !anActor )
480       return;
481
482     SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
483
484     IdList ids; extractIds( list, ids, '\0' );
485     IdList::const_iterator anIt = ids.begin(),
486                            aLast = ids.end();
487     for( ; anIt!=aLast; anIt++ )
488       if( const SMDS_MeshNode * n = aMesh->FindNode( *anIt ) )
489         newIndices.Add( n->GetID() );
490
491     selector()->AddOrRemoveIndex( sel.First(), newIndices, false );
492     highlight( sel.First(), true, true );
493
494     QStringList names, _ids; SalomeApp_Dialog::TypesList types;
495     selected( names, types, _ids );
496     dlg()->selectObject( names, types, _ids, false );
497 }
498
499 //=================================================================================
500 // name     : selectedIds
501 // purpose  :
502 //=================================================================================
503 void SMESHGUI_SelectionOp::selectedIds( const int id, IdList& list ) const
504 {
505   if( !dlg() )
506     return;
507
508   QStringList ids; dlg()->selectedObject( id, ids );
509   extractIds( ids, list );
510 }
511
512 //=================================================================================
513 // name     : extractIds
514 // purpose  :
515 //=================================================================================
516 void SMESHGUI_SelectionOp::extractIds( const QStringList& ids, IdList& list, const QChar idchar )
517 {
518   QStringList::const_iterator anIt = ids.begin(),
519                               aLast = ids.end();
520   QString id_str;
521   for( ; anIt!=aLast; anIt++ )
522   {
523     id_str = *anIt;
524     int pos = idchar=='\0' ? -1 : id_str.find( idchar );
525     int id = -1;
526     if( idchar=='\0' || pos>=0 )
527     {
528       id = id_str.mid( pos+1 ).toInt();
529       list.append( id );
530     }
531   }
532 }
533
534 //=================================================================================
535 // name     : extractIds
536 // purpose  :
537 //=================================================================================
538 void SMESHGUI_SelectionOp::extractIds( const QStringList& ids, IdList& list ) const
539 {
540   extractIds( ids, list, idChar() );
541 }