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