Salome HOME
*** empty log message ***
[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 /*
47   Class       : SMESHGUI_SelectionOp
48   Description : Base operation for all operations using object selection in viewer or objectbrowser
49                 through common widgets created by SalomeApp_Dialog::createObject
50 */
51
52 //=================================================================================
53 // name     : SMESHGUI_SelectionOp
54 // purpose  : 
55 //=================================================================================
56 SMESHGUI_SelectionOp::SMESHGUI_SelectionOp( const Selection_Mode mode )
57 : SMESHGUI_Operation(),
58   myDefSelectionMode( mode )
59 {
60 }
61
62 //=================================================================================
63 // name     : ~SMESHGUI_SelectionOp
64 // purpose  :
65 //=================================================================================
66 SMESHGUI_SelectionOp::~SMESHGUI_SelectionOp()
67 {
68   Filters::const_iterator anIt = myFilters.begin(),
69                           aLast = myFilters.end();
70   for( ; anIt!=aLast; anIt++ )
71     if( anIt.data() )
72       delete anIt.data();
73 }
74
75 //=================================================================================
76 // name     : startOperation
77 // purpose  :
78 //=================================================================================
79 void SMESHGUI_SelectionOp::startOperation()
80 {
81   SMESHGUI_Operation::startOperation();
82   if( dlg() )
83   {
84     disconnect( dlg(), SIGNAL( objectActivated( int ) ), this, SLOT( onActivateObject( int ) ) );
85     disconnect( dlg(), SIGNAL( objectDeactivated( int ) ), this, SLOT( onDeactivateObject( int ) ) );
86     disconnect( dlg(), SIGNAL( selectionChanged( int ) ), this, SLOT( onSelectionChanged( int ) ) );
87     connect( dlg(), SIGNAL( objectActivated( int ) ), this, SLOT( onActivateObject( int ) ) );
88     connect( dlg(), SIGNAL( objectDeactivated( int ) ), this, SLOT( onDeactivateObject( int ) ) );
89     connect( dlg(), SIGNAL( selectionChanged( int ) ), this, SLOT( onSelectionChanged( int ) ) );
90   }
91
92   myOldSelectionMode = selectionMode();
93   setSelectionMode( myDefSelectionMode );
94 }
95
96 //=================================================================================
97 // name     : removeCustomFilters
98 // purpose  :
99 //=================================================================================
100 void SMESHGUI_SelectionOp::removeCustomFilters() const
101 {
102   SalomeApp_SelectionMgr* mgr = selectionMgr();
103   if( !mgr )
104     return;
105     
106   Filters::const_iterator anIt = myFilters.begin(),
107                           aLast = myFilters.end();
108   for( ; anIt!=aLast; anIt++ )
109     if( anIt.data() )
110       mgr->removeFilter( anIt.data() );
111 }
112
113 //=================================================================================
114 // name     : commitOperation
115 // purpose  :
116 //=================================================================================
117 void SMESHGUI_SelectionOp::commitOperation()
118 {
119   removeCustomFilters();
120   setSelectionMode( myOldSelectionMode );
121   SMESHGUI_Operation::commitOperation();  
122 }
123
124 //=================================================================================
125 // name     : abortOperation
126 // purpose  :
127 //=================================================================================
128 void SMESHGUI_SelectionOp::abortOperation()
129 {
130   removeCustomFilters();
131   setSelectionMode( myOldSelectionMode );  
132   SMESHGUI_Operation::abortOperation();
133 }
134
135 //=================================================================================
136 // name     : selectionDone
137 // purpose  :
138 //=================================================================================
139 void SMESHGUI_SelectionOp::selectionDone()
140 {
141   if( !dlg() )
142     return;
143
144   if( selectionMode()!=ActorSelection )
145   {
146     SALOME_ListIO aList;
147     selectionMgr()->selectedObjects( aList, SVTK_Viewer::Type() );
148
149     if( aList.Extent() != 1 ) //we can select nodes or elements only within one mesh
150     {
151       dlg()->clearSelection();
152       return;
153     }    
154   }
155     
156   QStringList names, ids;
157   SalomeApp_Dialog::TypesList types;
158   selected( names, types, ids );
159   dlg()->selectObject( names, types, ids );
160 }
161
162 //=================================================================================
163 // name     : createFilter
164 // purpose  :
165 //=================================================================================
166 SUIT_SelectionFilter* SMESHGUI_SelectionOp::createFilter( const int ) const
167 {
168   return 0;
169 }
170
171 //=================================================================================
172 // name     : onActivateObject
173 // purpose  :
174 //=================================================================================
175 void SMESHGUI_SelectionOp::onActivateObject( int id )
176 {
177   SalomeApp_SelectionMgr* mgr = selectionMgr();
178   if( !mgr )
179     return;
180     
181   if( !myFilters.contains( id ) )
182     myFilters[ id ] = createFilter( id );
183
184   if( myFilters[ id ] )
185     mgr->installFilter( myFilters[ id ] );
186
187   selectionDone();
188 }
189
190 //=================================================================================
191 // name     : onDeactivateObject
192 // purpose  :
193 //=================================================================================
194 void SMESHGUI_SelectionOp::onDeactivateObject( int id )
195 {
196   SalomeApp_SelectionMgr* mgr = selectionMgr();
197   if( mgr && myFilters.contains( id ) && myFilters[ id ] )
198     mgr->removeFilter( myFilters[ id ] );
199 }
200
201 //=================================================================================
202 // name     : initDialog
203 // purpose  :
204 //=================================================================================
205 void SMESHGUI_SelectionOp::initDialog()
206 {
207   if( dlg() )
208   {
209     dlg()->clearSelection();
210     dlg()->deactivateAll();
211   }
212 }
213
214 //=================================================================================
215 // name     : initDialog
216 // purpose  :
217 //=================================================================================
218 void SMESHGUI_SelectionOp::onSelectionChanged( int )
219 {
220 }
221
222 //=======================================================================
223 // name    : selectionMode
224 // Purpose : Returns selection mode
225 //=======================================================================
226 Selection_Mode SMESHGUI_SelectionOp::selectionMode() const
227 {
228   SVTK_ViewWindow* wnd = viewWindow();
229   if( wnd )
230     return wnd->SelectionMode();
231   else
232     return ActorSelection;
233 }
234
235 //=======================================================================
236 // name    : setSelectionMode
237 // Purpose : Set selection mode
238 //=======================================================================
239 void SMESHGUI_SelectionOp::setSelectionMode( const Selection_Mode mode )
240 {
241   SVTK_ViewWindow* wnd = viewWindow();
242   if( wnd )
243     wnd->SetSelectionMode( mode );
244 }
245
246 //=======================================================================
247 // name    : highlight
248 // Purpose : Highlight object in 3d viewer
249 //=======================================================================
250 void SMESHGUI_SelectionOp::highlight( const Handle( SALOME_InteractiveObject )& obj,
251                                       const bool hilight, const bool immediately )
252 {
253   SVTK_ViewWindow* wnd = viewWindow();
254   if( wnd )
255     wnd->highlight( obj, hilight, immediately );
256 }
257
258 //=======================================================================
259 // name    : addOrRemoveIndex
260 // Purpose : Select/deselect cells of mesh
261 //=======================================================================
262 void SMESHGUI_SelectionOp::addOrRemoveIndex( const Handle( SALOME_InteractiveObject )& obj,
263                                              const TColStd_MapOfInteger& indices,
264                                              const bool isModeShift )
265 {
266   SVTK_Selector* sel = selector();
267   if( sel )
268     sel->AddOrRemoveIndex( obj, indices, isModeShift );
269 }
270
271 //=======================================================================
272 // name    : viewWindow
273 // Purpose : Get active view window
274 //=======================================================================
275 SVTK_ViewWindow* SMESHGUI_SelectionOp::viewWindow() const
276 {
277   return SMESH::GetViewWindow( getSMESHGUI() );
278 }
279
280 //=======================================================================
281 // name    : selector
282 // Purpose : Get selector
283 //=======================================================================
284 SVTK_Selector* SMESHGUI_SelectionOp::selector() const
285 {
286   SVTK_ViewWindow* wnd = viewWindow();
287   return wnd ? wnd->GetSelector() : 0;
288 }
289
290 //=======================================================================
291 // name    : typeById
292 // Purpose : Find type by id
293 //=======================================================================
294 int SMESHGUI_SelectionOp::typeById( const QString& str, const EntityType objtype ) const
295 {
296   SalomeApp_Study* _study = dynamic_cast<SalomeApp_Study*>( study() );
297   if( !_study )
298     return -1;
299
300   _PTR( Study ) st = _study->studyDS();
301
302   int res = -1;
303   if( objtype == Object )
304   {
305     SalomeApp_Study* _study = dynamic_cast<SalomeApp_Study*>( study() );
306     if( _study )
307     {
308       int t = SMESHGUI_Selection::type( str, _study->studyDS() );
309       if( t<0 )
310       {
311         //try to get GEOM type
312         _PTR( SObject ) sobj = st->FindObjectID( str.latin1() );
313         if( sobj )
314         {
315           GEOM::GEOM_Object_var obj = GEOM::GEOM_Object::_narrow( dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
316           if( !CORBA::is_nil( obj ) )
317             res = SMESHGUI_Dialog::prefix( "GEOM" ) + obj->GetType();
318         }
319       }
320       else
321         res = SMESHGUI_Dialog::prefix( "SMESH" ) + t;
322     }
323   }
324   else
325   {
326     int pos = str.find( idChar() );
327     QString entry = str.left( pos ),
328             _id = str.mid( pos+1 );
329     bool ok;
330     int id = _id.toInt( &ok );
331     if( ok )
332     {
333       _PTR( SObject ) sobj = st->FindObjectID( entry.latin1() );
334       SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
335       SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
336       if( !CORBA::is_nil( mesh ) )
337         res = SMESHGUI_Dialog::prefix( "SMESH element" ) + mesh->GetElementType( id, objtype==MeshElement );
338
339       else if( !CORBA::is_nil( submesh ) )
340         res = SMESHGUI_Dialog::prefix( "SMESH element" ) + submesh->GetElementType( id, objtype==MeshElement );
341     }
342   }
343
344   return res;
345 }
346
347 //=======================================================================
348 // name    : selected
349 // Purpose : Get names, types and ids of selected objects
350 //=======================================================================
351 void SMESHGUI_SelectionOp::selected( QStringList& names,
352                                      SalomeApp_Dialog::TypesList& types,
353                                      QStringList& ids ) const
354 {
355   SUIT_DataOwnerPtrList list; selectionMgr()->selected( list );
356   SUIT_DataOwnerPtrList::const_iterator anIt = list.begin(),
357                                         aLast = list.end();
358   for( ; anIt!=aLast; anIt++ )
359   {
360     SalomeApp_DataOwner* owner = dynamic_cast<SalomeApp_DataOwner*>( (*anIt).operator->() );
361     SalomeApp_SVTKDataOwner* vtkowner = dynamic_cast<SalomeApp_SVTKDataOwner*>( (*anIt).operator->() );
362
363     if( vtkowner )
364     {
365       QString id_str = QString( "%1%2%3" ).arg( vtkowner->entry() ).arg( idChar() ), current_id_str;
366       Selection_Mode mode = vtkowner->GetMode();
367       EntityType objtype = mode == NodeSelection ? MeshNode : MeshElement;
368       const TColStd_IndexedMapOfInteger& ownerids = vtkowner->GetIds();
369
370       for( int i=1, n=ownerids.Extent(); i<=n; i++ )
371       {
372         int curid = ownerids( i );
373         current_id_str = id_str.arg( curid );
374         ids.append( current_id_str );
375         types.append( typeById( current_id_str, objtype ) );
376         names.append( QString( "%1" ).arg( curid ) );
377       }
378     }
379
380     else if( owner )
381     {
382       QString id = owner->entry();
383       ids.append( id );
384       types.append( typeById( id, Object ) );
385       names.append( owner->IO()->getName() );
386     }
387   }
388 }
389
390 //=======================================================================
391 // name    : idChar
392 // Purpose : Char using to divide <entry> and <id> in string id representation. By default, '#'
393 //=======================================================================
394 QChar SMESHGUI_SelectionOp::idChar() const
395 {
396   return '#';
397 }
398
399 //=================================================================================
400 // name     : mesh
401 // purpose  :
402 //=================================================================================
403 SMESH::SMESH_Mesh_var SMESHGUI_SelectionOp::mesh() const
404 {
405   if( selectionMode()==ActorSelection )
406     return SMESH::SMESH_Mesh::_nil();
407     
408   SALOME_ListIO sel; selectionMgr()->selectedObjects( sel, SVTK_Viewer::Type() );
409   if( sel.Extent()==1 )
410     return SMESH::GetMeshByIO( sel.First() );
411   else
412     return SMESH::SMESH_Mesh::_nil();
413 }
414
415 //=================================================================================
416 // name     : actor
417 // purpose  :
418 //=================================================================================
419 SMESH_Actor* SMESHGUI_SelectionOp::actor() const
420 {
421   SMESH::SMESH_Mesh_var m = mesh();
422   if( !m->_is_nil() )
423     return SMESH::FindActorByObject( m.in() );
424   else
425     return 0;
426 }
427
428 //=================================================================================
429 // name     : onTextChanged
430 // purpose  :
431 //=================================================================================
432 void SMESHGUI_SelectionOp::onTextChanged( int, const QStringList& list )
433 {
434     if( !dlg() )
435       return;
436
437     TColStd_MapOfInteger newIndices;
438
439     SALOME_ListIO sel; selectionMgr()->selectedObjects( sel );
440     SMESH_Actor* anActor = actor();
441     if( sel.Extent()==0 || !anActor )
442       return;
443
444     SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
445
446     IdList ids; extractIds( list, ids, '\0' );
447     IdList::const_iterator anIt = ids.begin(),
448                            aLast = ids.end();
449     for( ; anIt!=aLast; anIt++ )
450       if( const SMDS_MeshNode * n = aMesh->FindNode( *anIt ) )
451         newIndices.Add( n->GetID() );
452
453     selector()->AddOrRemoveIndex( sel.First(), newIndices, false );
454     highlight( sel.First(), true, true );
455
456     QStringList names, _ids; SalomeApp_Dialog::TypesList types;
457     selected( names, types, _ids );
458     dlg()->selectObject( names, types, _ids, false );
459 }
460
461 //=================================================================================
462 // name     : selectedIds
463 // purpose  :
464 //=================================================================================
465 void SMESHGUI_SelectionOp::selectedIds( const int id, IdList& list ) const
466 {
467   if( !dlg() )
468     return;
469
470   QStringList ids; dlg()->selectedObject( id, ids );
471   extractIds( ids, list );
472 }
473
474 //=================================================================================
475 // name     : extractIds
476 // purpose  :
477 //=================================================================================
478 void SMESHGUI_SelectionOp::extractIds( const QStringList& ids, IdList& list, const QChar idchar )
479 {
480   QStringList::const_iterator anIt = ids.begin(),
481                               aLast = ids.end();
482   QString id_str;
483   for( ; anIt!=aLast; anIt++ )
484   {
485     id_str = *anIt;
486     int pos = idchar=='\0' ? -1 : id_str.find( idchar );
487     int id = -1;
488     if( idchar=='\0' || pos>=0 )
489     {
490       id = id_str.mid( pos+1 ).toInt();
491       list.append( id );
492     }
493   }
494 }
495
496 //=================================================================================
497 // name     : extractIds
498 // purpose  :
499 //=================================================================================
500 void SMESHGUI_SelectionOp::extractIds( const QStringList& ids, IdList& list ) const
501 {
502   extractIds( ids, list, idChar() );
503 }