Salome HOME
6adcbc1fde5658102fdd5868ae61177b8485652d
[modules/smesh.git] / src / StdMeshersGUI / StdMeshersGUI_SubShapeSelectorWdg.cxx
1 //  Copyright (C) 2007-2010  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.
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 // File   : StdMeshersGUI_SubShapeSelectorWdg.cxx
21 // Author : Open CASCADE S.A.S. (dmv)
22 // SMESH includes
23 //
24 #include "StdMeshersGUI_SubShapeSelectorWdg.h"
25
26 // SMESH Includes
27 #include <SMESH_Type.h>
28 #include "SMESHGUI_MeshUtils.h"
29 #include <SMESH_Actor.h>
30 #include <SMESH_PreviewActorsCollection.h>
31 #include <SMESH_ActorUtils.h>
32 #include "SMESHGUI_GroupUtils.h"
33 #include "SMESH_Gen_i.hxx"
34 #include "SMESHGUI_GEOMGenUtils.h"
35
36 // SVTK Includes
37 #include <SVTK_ViewWindow.h>
38 #include <SVTK_ViewModel.h>
39 #include <SVTK_ViewWindow.h>
40 #include <SVTK_Selector.h>
41
42 // SALOME GUI includes
43 #include <SALOME_ListIO.hxx>
44 #include <LightApp_SelectionMgr.h>
45 #include <SALOME_ListIteratorOfListIO.hxx>
46
47 // SUIT Includes
48 #include <SUIT_ResourceMgr.h>
49
50 // GEOM Includes
51 #include <GEOMBase.h>
52
53 // Qt includes
54 #include <QPushButton>
55 #include <QGridLayout>
56 #include <QListWidget>
57 #include <QCheckBox>
58 #include <QLineEdit>
59
60 // OCCT includes
61 #include <TColStd_MapOfInteger.hxx>
62 #include <TColStd_IndexedMapOfInteger.hxx>
63 #include <TopoDS_Shape.hxx>
64 #include <TopExp.hxx>
65 #include <TopExp_Explorer.hxx>
66
67 // SALOME KERNEL includes
68 #include <SALOMEDS_SObject.hxx>
69
70 #define SPACING 6
71 #define MARGIN 0
72
73 //================================================================================
74 /*!
75  *  Constructor
76  */
77 //================================================================================
78
79 StdMeshersGUI_SubShapeSelectorWdg
80 ::StdMeshersGUI_SubShapeSelectorWdg( QWidget * parent ): 
81   QWidget( parent ),
82   myPreviewActor( 0 ),
83   myMaxSize( -1 )
84 {
85   QPixmap image0( SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap( "SMESH", tr( "ICON_SELECT" ) ) );
86
87   QGridLayout* edgesLayout = new QGridLayout( this );
88   edgesLayout->setMargin( MARGIN );
89   edgesLayout->setSpacing( SPACING );
90   
91   myListWidget    = new QListWidget( this );
92   myAddButton    = new QPushButton( tr( "SMESH_BUT_ADD" ),    this );
93   myRemoveButton = new QPushButton( tr( "SMESH_BUT_REMOVE" ), this );      
94   myListWidget->setSelectionMode( QListWidget::ExtendedSelection );
95
96   edgesLayout->addWidget(myListWidget,   0, 0, 3, 3);
97   edgesLayout->addWidget(myAddButton,    0, 4);
98   edgesLayout->addWidget(myRemoveButton, 1, 4);
99
100   edgesLayout->setRowStretch(2, 5);
101   edgesLayout->setColumnStretch(2, 5);
102
103   setLayout( edgesLayout );
104   setMinimumWidth( 300 );
105
106   mySubShType = TopAbs_EDGE;
107
108   init();
109 }
110
111 //================================================================================
112 /*!
113  *  Destructor
114  */
115 //================================================================================
116
117 StdMeshersGUI_SubShapeSelectorWdg::~StdMeshersGUI_SubShapeSelectorWdg()
118 {
119   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) {
120     if ( myPreviewActor ) {
121       myPreviewActor->RemoveFromRender( myRenderer );
122       aViewWindow->Repaint();
123
124       delete myPreviewActor;
125       myPreviewActor = 0;
126     }
127   }
128   myEntry = "";
129   myParamValue = "";
130   myMainShape.Nullify();
131 }
132
133 //================================================================================
134 /*!
135  *  Create a layout, initialize fields
136  */
137 //================================================================================
138
139 void StdMeshersGUI_SubShapeSelectorWdg::init()
140 {
141   myParamValue = "";
142   myIsNotCorrected = true; // to dont call the GetCorrectedValue method twice
143   myListOfIDs.clear();
144   mySelectedIDs.clear();
145
146   mySMESHGUI     = SMESHGUI::GetSMESHGUI();
147   mySelectionMgr = SMESH::GetSelectionMgr( mySMESHGUI );
148   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
149
150   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
151     aViewWindow->SetSelectionMode( ActorSelection );
152
153   connect( myAddButton,    SIGNAL(clicked()), SLOT(onAdd()));
154   connect( myRemoveButton, SIGNAL(clicked()), SLOT(onRemove()));
155   
156   connect( mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
157   connect( myListWidget,   SIGNAL(itemSelectionChanged()),    this, SLOT(onListSelectionChanged()));
158
159   updateState();
160 }
161
162 //================================================================================
163 /*!
164  *  Create a layout, initialize fields
165  */
166 //================================================================================
167
168 void StdMeshersGUI_SubShapeSelectorWdg::showPreview( bool visible)
169 {
170   if ( !myPreviewActor )
171     return;
172
173   if ( myIsShown != visible ) {
174     myPreviewActor->SetShown( visible );
175     
176     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
177       aViewWindow->Repaint();
178
179     myIsShown = visible;
180   }
181 }
182
183 //=================================================================================
184 // function : SelectionIntoArgument()
185 // purpose  : Called when selection as changed or other case
186 //=================================================================================
187 void StdMeshersGUI_SubShapeSelectorWdg::SelectionIntoArgument()
188 {
189   if ( !myPreviewActor )
190     return;
191
192   mySelectedIDs.clear();
193
194   // get selected mesh
195   SALOME_ListIO aList;
196   mySelectionMgr->selectedObjects( aList );
197   int nbSel = aList.Extent();
198
199   if (nbSel < 1)
200     return;
201
202   SALOME_ListIteratorOfListIO anIt (aList);
203     
204   for ( ; anIt.More(); anIt.Next()) { // Loop on selected objects
205     Handle(SALOME_InteractiveObject) IO = anIt.Value();
206
207     GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( IO->getEntry() );  
208     if ( !CORBA::is_nil( aGeomObj ) ) { // Selected Object From Study
209       GEOM::GEOM_Object_ptr aGeomFatherObj = aGeomObj->GetMainShape();
210       QString aFatherEntry = "";
211       QString aMainFatherEntry = "";
212       TopoDS_Shape shape;
213       if ( !CORBA::is_nil( aGeomFatherObj ) ) {
214         // Get Main Shape
215         GEOM::GEOM_Object_var aGeomMain = GetGeomObjectByEntry( myEntry );
216         if ( !CORBA::is_nil( aGeomMain ) && aGeomMain->GetType() == 37 ) {  // Main Shape is a Group
217           GEOM::GEOM_Object_ptr aMainFatherObj = aGeomMain->GetMainShape();
218           if ( !CORBA::is_nil( aMainFatherObj ) )
219             aMainFatherEntry = aMainFatherObj->GetStudyEntry();
220         }
221         aFatherEntry = aGeomFatherObj->GetStudyEntry();
222       }
223       
224       if ( aFatherEntry != "" && ( aFatherEntry == myEntry || aFatherEntry == aMainFatherEntry ) ) {
225         if ( aGeomObj->GetType() == 37 /*GEOM_GROUP*/ ) { // Selected Group that belongs the main object
226           GEOMBase::GetShape(aGeomObj, shape); 
227           if ( !shape.IsNull() ) {
228             TopExp_Explorer exp( shape, mySubShType );
229             for ( ; exp.More(); exp.Next() ) {
230               int index = myPreviewActor->GetIndexByShape( exp.Current() );
231               if ( index ) {
232                 mySelectedIDs.append( index );
233                 myPreviewActor->HighlightID( index );
234               }
235             }
236           }
237         } else if ( aGeomObj->GetType() == 28 /*GEOM_SUBSHAPE*/  ) {
238           GEOMBase::GetShape(aGeomObj, shape); 
239           if ( !shape.IsNull() && shape.ShapeType() == mySubShType ) {
240             int index = myPreviewActor->GetIndexByShape( shape );
241             if ( index ) {
242               mySelectedIDs.append( index );
243               myPreviewActor->HighlightID( index );
244             }
245           }
246         }
247       }
248     } else { // Selected Actor from Actor Collection
249       QString anEntry = IO->getEntry();
250       QString str = "_";
251       int index = anEntry.lastIndexOf( str );
252       anEntry.remove(0, index+1);
253       int ind = anEntry.toInt();
254       if ( ind )
255         mySelectedIDs.append( ind );
256     }
257   }
258 }
259
260 //=================================================================================
261 // function : onAdd()
262 // purpose  : Called when Add Button Clicked
263 //=================================================================================
264 void StdMeshersGUI_SubShapeSelectorWdg::onAdd()
265 {
266   if ( mySelectedIDs.size() < 1 )
267     return;
268
269   myListWidget->blockSignals( true );
270   for (int i = 0; i < mySelectedIDs.size() && (myMaxSize == -1 || myListOfIDs.size() < myMaxSize); i++) {
271     if ( myListOfIDs.indexOf( mySelectedIDs.at(i) ) == -1 ) {
272       QString anID = QString(" %1").arg( mySelectedIDs.at(i) );
273
274       QListWidgetItem* anItem = new QListWidgetItem( anID, myListWidget );
275       anItem->setSelected(true);
276       
277       myListOfIDs.append( mySelectedIDs.at(i) );
278     }
279   }
280   onListSelectionChanged();
281   myListWidget->blockSignals( false );
282   myAddButton->setEnabled( myMaxSize == -1 || myListOfIDs.size() < myMaxSize );
283 }
284          
285 //=================================================================================
286 // function : onRemove()
287 // purpose  : Called when Remove Button Clicked
288 //=================================================================================
289 void StdMeshersGUI_SubShapeSelectorWdg::onRemove()
290 {
291   if ( myListWidget->count() < 1 )
292     return;
293
294   myListWidget->blockSignals( true );
295   QList<QListWidgetItem*> selItems = myListWidget->selectedItems();
296   QListWidgetItem* item;
297   foreach(item, selItems) {
298     QString idStr = item->text();
299     int id = idStr.toInt();
300
301     int index = myListOfIDs.indexOf( id );
302     myListOfIDs.removeAt( index );
303     delete item;
304   }
305
306   onListSelectionChanged();
307   myListWidget->blockSignals( false );
308   
309   myAddButton->setEnabled( true );
310 }
311
312 //=================================================================================
313 // function : onListSelectionChanged()
314 // purpose  : Called when selection in element list is changed
315 //=================================================================================
316 void StdMeshersGUI_SubShapeSelectorWdg::onListSelectionChanged()
317 {
318   if ( !myPreviewActor )
319     return;
320
321   mySelectionMgr->clearSelected();
322   TColStd_MapOfInteger aIndexes;
323   QList<QListWidgetItem*> selItems = myListWidget->selectedItems();
324   QListWidgetItem* anItem;
325   foreach(anItem, selItems)
326     myPreviewActor->HighlightID( anItem->text().toInt() );
327 }
328
329 //=================================================================================
330 // function : setGeomShape
331 // purpose  : Called to set geometry
332 //================================================================================
333 void StdMeshersGUI_SubShapeSelectorWdg::SetGeomShapeEntry( const QString& theEntry )
334 {
335   if ( theEntry != "") {
336     myParamValue = theEntry;
337     myEntry = theEntry;
338     myGeomShape = GetTopoDSByEntry( theEntry );
339     updateState();
340     myIsNotCorrected = true;
341   }
342 }
343
344 //=================================================================================
345 // function : updateState
346 // purpose  : update Widget state
347 //=================================================================================
348 void StdMeshersGUI_SubShapeSelectorWdg::updateState()
349 {
350   bool state = false;
351   if ( !myGeomShape.IsNull() )
352     state = true;
353   
354   myListWidget->setEnabled( state );
355   myAddButton->setEnabled( state );
356   myRemoveButton->setEnabled( state );
357   
358   if (state) {
359     myPreviewActor = new SMESH_PreviewActorsCollection();
360     myPreviewActor->SetSelector( mySelector );
361     myPreviewActor->Init( myGeomShape, mySubShType, myEntry );
362     myPreviewActor->SetShown( false );
363     myIsShown = false;
364     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) {
365       myRenderer = aViewWindow->getRenderer();
366       myPreviewActor->AddToRender( myRenderer );
367       aViewWindow->Repaint();
368     }
369   }
370 }
371
372 //=================================================================================
373 // function : GetGeomObjectByEntry
374 // purpose  : Called to get GeomObject
375 //=================================================================================
376 GEOM::GEOM_Object_var StdMeshersGUI_SubShapeSelectorWdg::GetGeomObjectByEntry( const QString& theEntry )
377 {
378   GEOM::GEOM_Object_var aGeomObj;
379   SALOMEDS::Study_var aStudy = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
380   if (aStudy != 0) {
381     SALOMEDS::SObject_var aSObj = aStudy->FindObjectID( theEntry.toLatin1().data() );
382     SALOMEDS::GenericAttribute_var anAttr;
383
384     if (!aSObj->_is_nil() && aSObj->FindAttribute(anAttr, "AttributeIOR")) {
385       SALOMEDS::AttributeIOR_var anIOR = SALOMEDS::AttributeIOR::_narrow(anAttr);
386       CORBA::String_var aVal = anIOR->Value();
387       CORBA::Object_var obj = aStudy->ConvertIORToObject(aVal);
388       aGeomObj = GEOM::GEOM_Object::_narrow(obj);
389     }
390   }
391   return aGeomObj;
392 }
393
394 //=================================================================================
395 // function : setObjectByEntry
396 // purpose  : Called to get GeomObject
397 //=================================================================================
398 TopoDS_Shape StdMeshersGUI_SubShapeSelectorWdg::GetTopoDSByEntry( const QString& theEntry )
399 {
400   TopoDS_Shape shape;
401   GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( theEntry );
402   GEOMBase::GetShape(aGeomObj, shape);
403   return shape;
404 }
405
406 //=================================================================================
407 // function : GetListOfIds
408 // purpose  : Called to get the list of SubShapes IDs
409 //=================================================================================
410 SMESH::long_array_var StdMeshersGUI_SubShapeSelectorWdg::GetListOfIDs()
411 {
412   SMESH::long_array_var anArray = new SMESH::long_array;
413
414   if ( myMainEntry != "" && myIsNotCorrected )
415     myListOfIDs = GetCorrectedListOfIDs( true );
416
417   int size = myListOfIDs.size();
418   anArray->length( size );
419   if ( size ) {
420     for (int i = 0; i < size; i++) {
421         anArray[i] = myListOfIDs.at(i);
422     }
423   }
424   return anArray;
425 }
426
427 //=================================================================================
428 // function : SetListOfIds
429 // purpose  : Called to set the list of SubShapes IDs
430 //=================================================================================
431 void StdMeshersGUI_SubShapeSelectorWdg::SetListOfIDs( SMESH::long_array_var theIds)
432 {
433   mySelectedIDs.clear();
434   myListOfIDs.clear();
435   int size = theIds->length();
436   for ( int i = 0; i < size; i++ )
437     mySelectedIDs.append( theIds[ i ] );
438
439   mySelectedIDs = GetCorrectedListOfIDs( false );
440   onAdd();
441 }
442
443 //=================================================================================
444 // function : SetMainShapeEntry
445 // purpose  : Called to set the Main Object Entry
446 //=================================================================================
447 void StdMeshersGUI_SubShapeSelectorWdg::SetMainShapeEntry( const QString& theEntry )
448 {
449   myMainEntry = theEntry;
450   myMainShape = GetTopoDSByEntry( theEntry );
451   myIsNotCorrected = true;
452 }
453
454 //=================================================================================
455 // function : GetMainShapeEntry
456 // purpose  : Called to get the Main Object Entry
457 //=================================================================================
458 const char* StdMeshersGUI_SubShapeSelectorWdg::GetMainShapeEntry()
459 {
460   if ( myMainEntry == "")
461     return myEntry.toLatin1().data();
462
463   return myMainEntry.toLatin1().data();
464 }
465
466 //=================================================================================
467 // function : GetCorrectedListOfIds
468 // purpose  : Called to convert the list of IDs from subshape IDs to main shape IDs
469 //=================================================================================
470 QList<int> StdMeshersGUI_SubShapeSelectorWdg::GetCorrectedListOfIDs( bool fromSubshapeToMainshape )
471 {
472   if ( ( myMainShape.IsNull() || myGeomShape.IsNull() ) &&  fromSubshapeToMainshape )
473     return myListOfIDs;
474   else   if ( ( myMainShape.IsNull() || myGeomShape.IsNull() ) &&  !fromSubshapeToMainshape )
475     return mySelectedIDs;
476
477   QList<int> aList;
478   TopTools_IndexedMapOfShape   aGeomMap;
479   TopTools_IndexedMapOfShape   aMainMap;
480   TopExp::MapShapes(myGeomShape, aGeomMap);
481   TopExp::MapShapes(myMainShape, aMainMap);
482
483   if ( fromSubshapeToMainshape ) { // convert indexes from subshape to mainshape
484     int size = myListOfIDs.size();
485     for (int i = 0; i < size; i++) {
486       TopoDS_Shape aSubShape = aGeomMap.FindKey( myListOfIDs.at(i) );
487       int index = aMainMap.FindIndex( aSubShape );
488       aList.append( index );
489     }
490     myIsNotCorrected = false;
491   } else { // convert indexes from main shape to subshape
492     int size = mySelectedIDs.size();
493     for (int i = 0; i < size; i++) {
494       TopoDS_Shape aSubShape = aMainMap.FindKey( mySelectedIDs.at(i) );
495       int index = aGeomMap.FindIndex( aSubShape );
496       aList.append( index );
497     }
498   }
499
500   return aList;
501 }