Salome HOME
Merge from V5_1_main 14/05/2010
[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   myAddButton->setEnabled( false );
147   myRemoveButton->setEnabled( false );
148
149   mySMESHGUI     = SMESHGUI::GetSMESHGUI();
150   mySelectionMgr = SMESH::GetSelectionMgr( mySMESHGUI );
151   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
152
153   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
154     aViewWindow->SetSelectionMode( ActorSelection );
155
156   connect( myAddButton,    SIGNAL(clicked()), SLOT(onAdd()));
157   connect( myRemoveButton, SIGNAL(clicked()), SLOT(onRemove()));
158   
159   connect( mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
160   connect( myListWidget,   SIGNAL(itemSelectionChanged()),    this, SLOT(onListSelectionChanged()));
161
162   updateState();
163 }
164
165 //================================================================================
166 /*!
167  *  Create a layout, initialize fields
168  */
169 //================================================================================
170
171 void StdMeshersGUI_SubShapeSelectorWdg::showPreview( bool visible)
172 {
173   if ( !myPreviewActor )
174     return;
175
176   if ( myIsShown != visible ) {
177     myPreviewActor->SetShown( visible );
178     
179     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
180       aViewWindow->Repaint();
181
182     myIsShown = visible;
183   }
184 }
185
186 //=================================================================================
187 // function : SelectionIntoArgument()
188 // purpose  : Called when selection as changed or other case
189 //=================================================================================
190 void StdMeshersGUI_SubShapeSelectorWdg::SelectionIntoArgument()
191 {
192   if ( !myPreviewActor )
193     return;
194
195   mySelectedIDs.clear();
196
197   // get selected mesh
198   SALOME_ListIO aList;
199   mySelectionMgr->selectedObjects( aList );
200   int nbSel = aList.Extent();
201
202   if (nbSel > 0) {
203     SALOME_ListIteratorOfListIO anIt (aList);
204     
205     for ( ; anIt.More(); anIt.Next()) { // Loop on selected objects
206       Handle(SALOME_InteractiveObject) IO = anIt.Value();
207       
208       GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( IO->getEntry() );  
209       if ( !CORBA::is_nil( aGeomObj ) ) { // Selected Object From Study
210         GEOM::GEOM_Object_ptr aGeomFatherObj = aGeomObj->GetMainShape();
211         QString aFatherEntry = "";
212         QString aMainFatherEntry = "";
213         TopoDS_Shape shape;
214         if ( !CORBA::is_nil( aGeomFatherObj ) ) {
215           // Get Main Shape
216           GEOM::GEOM_Object_var aGeomMain = GetGeomObjectByEntry( myEntry );
217           if ( !CORBA::is_nil( aGeomMain ) && aGeomMain->GetType() == 37 ) {  // Main Shape is a Group
218             GEOM::GEOM_Object_ptr aMainFatherObj = aGeomMain->GetMainShape();
219             if ( !CORBA::is_nil( aMainFatherObj ) )
220               aMainFatherEntry = aMainFatherObj->GetStudyEntry();
221           }
222           aFatherEntry = aGeomFatherObj->GetStudyEntry();
223         }
224         
225         if ( aFatherEntry != "" && ( aFatherEntry == myEntry || aFatherEntry == aMainFatherEntry ) ) {
226           if ( aGeomObj->GetType() == 37 /*GEOM_GROUP*/ ) { // Selected Group that belongs the main object
227             GEOMBase::GetShape(aGeomObj, shape); 
228             if ( !shape.IsNull() ) {
229               TopExp_Explorer exp( shape, mySubShType );
230               for ( ; exp.More(); exp.Next() ) {
231                 int index = myPreviewActor->GetIndexByShape( exp.Current() );
232                 if ( index ) {
233                   mySelectedIDs.append( index );
234                   myPreviewActor->HighlightID( index );
235                 }
236               }
237             }
238           } else if ( aGeomObj->GetType() == 28 /*GEOM_SUBSHAPE*/  ) {
239             GEOMBase::GetShape(aGeomObj, shape); 
240             if ( !shape.IsNull() && shape.ShapeType() == mySubShType ) {
241               int index = myPreviewActor->GetIndexByShape( shape );
242               if ( index ) {
243                 mySelectedIDs.append( index );
244                 myPreviewActor->HighlightID( index );
245               }
246             }
247           }
248         }
249       } else { // Selected Actor from Actor Collection
250         QString anEntry = IO->getEntry();
251         QString str = "_";
252         int index = anEntry.lastIndexOf( str );
253         anEntry.remove(0, index+1);
254         int ind = anEntry.toInt();
255         if ( ind )
256           mySelectedIDs.append( ind );
257       }
258     }
259   }
260   // update add button
261   myAddButton->setEnabled( myListWidget->count() < myMaxSize && mySelectedIDs.size() > 0 && ( mySelectedIDs.size() <= myMaxSize || myMaxSize == -1 ) );
262
263   //Connect Selected Ids in viewer and dialog's Ids list
264   myListWidget->clearSelection();
265   if ( mySelectedIDs.size() > 0 ) {
266     for (int i = 0; i < mySelectedIDs.size(); i++) {
267       QString anID = QString(" %1").arg( mySelectedIDs.at(i) );
268       QList<QListWidgetItem*> anItems = myListWidget->findItems ( anID, Qt::MatchExactly );
269       QListWidgetItem* item;
270       foreach(item, anItems)
271         item->setSelected(true);
272     }
273   }
274 }
275
276 //=================================================================================
277 // function : onAdd()
278 // purpose  : Called when Add Button Clicked
279 //=================================================================================
280 void StdMeshersGUI_SubShapeSelectorWdg::onAdd()
281 {
282   if ( mySelectedIDs.size() < 1 )
283     return;
284
285   myListWidget->blockSignals( true );
286   for (int i = 0; i < mySelectedIDs.size() && (myMaxSize == -1 || myListOfIDs.size() < myMaxSize); i++) {
287     if ( myListOfIDs.indexOf( mySelectedIDs.at(i) ) == -1 ) {
288       QString anID = QString(" %1").arg( mySelectedIDs.at(i) );
289
290       QListWidgetItem* anItem = new QListWidgetItem( anID, myListWidget );
291       anItem->setSelected(true);
292       
293       myListOfIDs.append( mySelectedIDs.at(i) );
294     }
295   }
296   onListSelectionChanged();
297   myListWidget->blockSignals( false );
298   myAddButton->setEnabled( myMaxSize == -1 || myListOfIDs.size() < myMaxSize );
299 }
300          
301 //=================================================================================
302 // function : onRemove()
303 // purpose  : Called when Remove Button Clicked
304 //=================================================================================
305 void StdMeshersGUI_SubShapeSelectorWdg::onRemove()
306 {
307   if ( myListWidget->count() < 1 )
308     return;
309
310   myListWidget->blockSignals( true );
311   QList<QListWidgetItem*> selItems = myListWidget->selectedItems();
312   QListWidgetItem* item;
313   foreach(item, selItems) {
314     QString idStr = item->text();
315     int id = idStr.toInt();
316
317     int index = myListOfIDs.indexOf( id );
318     myListOfIDs.removeAt( index );
319     delete item;
320   }
321
322   onListSelectionChanged();
323   myListWidget->blockSignals( false );
324   
325   myAddButton->setEnabled( true );
326 }
327
328 //=================================================================================
329 // function : onListSelectionChanged()
330 // purpose  : Called when selection in element list is changed
331 //=================================================================================
332 void StdMeshersGUI_SubShapeSelectorWdg::onListSelectionChanged()
333 {
334   if ( !myPreviewActor )
335     return;
336
337   mySelectionMgr->clearSelected();
338   TColStd_MapOfInteger aIndexes;
339   QList<QListWidgetItem*> selItems = myListWidget->selectedItems();
340   QListWidgetItem* anItem;
341   foreach(anItem, selItems)
342     myPreviewActor->HighlightID( anItem->text().toInt() );
343
344   // update remove button
345   myRemoveButton->setEnabled( selItems.size() > 0 );
346 }
347
348 //=================================================================================
349 // function : setGeomShape
350 // purpose  : Called to set geometry
351 //================================================================================
352 void StdMeshersGUI_SubShapeSelectorWdg::SetGeomShapeEntry( const QString& theEntry )
353 {
354   if ( theEntry != "") {
355     myParamValue = theEntry;
356     myEntry = theEntry;
357     myGeomShape = GetTopoDSByEntry( theEntry );
358     updateState();
359     myIsNotCorrected = true;
360   }
361 }
362
363 //=================================================================================
364 // function : updateState
365 // purpose  : update Widget state
366 //=================================================================================
367 void StdMeshersGUI_SubShapeSelectorWdg::updateState()
368 {
369   bool state = false;
370   if ( !myGeomShape.IsNull() )
371     state = true;
372   
373   myListWidget->setEnabled( state );
374   myAddButton->setEnabled( mySelectedIDs.size() > 0 );
375   
376   if (state) {
377     myPreviewActor = new SMESH_PreviewActorsCollection();
378     myPreviewActor->SetSelector( mySelector );
379     myPreviewActor->Init( myGeomShape, mySubShType, myEntry );
380     myPreviewActor->SetShown( false );
381     myIsShown = false;
382     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) {
383       myRenderer = aViewWindow->getRenderer();
384       myPreviewActor->AddToRender( myRenderer );
385       aViewWindow->Repaint();
386     }
387   }
388 }
389
390 //=================================================================================
391 // function : GetGeomObjectByEntry
392 // purpose  : Called to get GeomObject
393 //=================================================================================
394 GEOM::GEOM_Object_var StdMeshersGUI_SubShapeSelectorWdg::GetGeomObjectByEntry( const QString& theEntry )
395 {
396   GEOM::GEOM_Object_var aGeomObj;
397   SALOMEDS::Study_var aStudy = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
398   if (aStudy != 0) {
399     SALOMEDS::SObject_var aSObj = aStudy->FindObjectID( theEntry.toLatin1().data() );
400     SALOMEDS::GenericAttribute_var anAttr;
401
402     if (!aSObj->_is_nil() && aSObj->FindAttribute(anAttr, "AttributeIOR")) {
403       SALOMEDS::AttributeIOR_var anIOR = SALOMEDS::AttributeIOR::_narrow(anAttr);
404       CORBA::String_var aVal = anIOR->Value();
405       CORBA::Object_var obj = aStudy->ConvertIORToObject(aVal);
406       aGeomObj = GEOM::GEOM_Object::_narrow(obj);
407     }
408   }
409   return aGeomObj;
410 }
411
412 //=================================================================================
413 // function : setObjectByEntry
414 // purpose  : Called to get GeomObject
415 //=================================================================================
416 TopoDS_Shape StdMeshersGUI_SubShapeSelectorWdg::GetTopoDSByEntry( const QString& theEntry )
417 {
418   TopoDS_Shape shape;
419   GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( theEntry );
420   GEOMBase::GetShape(aGeomObj, shape);
421   return shape;
422 }
423
424 //=================================================================================
425 // function : GetListOfIds
426 // purpose  : Called to get the list of SubShapes IDs
427 //=================================================================================
428 SMESH::long_array_var StdMeshersGUI_SubShapeSelectorWdg::GetListOfIDs()
429 {
430   SMESH::long_array_var anArray = new SMESH::long_array;
431
432   if ( myMainEntry != "" && myIsNotCorrected )
433     myListOfIDs = GetCorrectedListOfIDs( true );
434
435   int size = myListOfIDs.size();
436   anArray->length( size );
437   if ( size ) {
438     for (int i = 0; i < size; i++) {
439         anArray[i] = myListOfIDs.at(i);
440     }
441   }
442   return anArray;
443 }
444
445 //=================================================================================
446 // function : SetListOfIds
447 // purpose  : Called to set the list of SubShapes IDs
448 //=================================================================================
449 void StdMeshersGUI_SubShapeSelectorWdg::SetListOfIDs( SMESH::long_array_var theIds)
450 {
451   mySelectedIDs.clear();
452   myListOfIDs.clear();
453   int size = theIds->length();
454   for ( int i = 0; i < size; i++ )
455     mySelectedIDs.append( theIds[ i ] );
456
457   mySelectedIDs = GetCorrectedListOfIDs( false );
458   onAdd();
459 }
460
461 //=================================================================================
462 // function : SetMainShapeEntry
463 // purpose  : Called to set the Main Object Entry
464 //=================================================================================
465 void StdMeshersGUI_SubShapeSelectorWdg::SetMainShapeEntry( const QString& theEntry )
466 {
467   myMainEntry = theEntry;
468   myMainShape = GetTopoDSByEntry( theEntry );
469   myIsNotCorrected = true;
470 }
471
472 //=================================================================================
473 // function : GetMainShapeEntry
474 // purpose  : Called to get the Main Object Entry
475 //=================================================================================
476 const char* StdMeshersGUI_SubShapeSelectorWdg::GetMainShapeEntry()
477 {
478   if ( myMainEntry == "")
479     return myEntry.toLatin1().data();
480
481   return myMainEntry.toLatin1().data();
482 }
483
484 //=================================================================================
485 // function : GetCorrectedListOfIds
486 // purpose  : Called to convert the list of IDs from subshape IDs to main shape IDs
487 //=================================================================================
488 QList<int> StdMeshersGUI_SubShapeSelectorWdg::GetCorrectedListOfIDs( bool fromSubshapeToMainshape )
489 {
490   if ( ( myMainShape.IsNull() || myGeomShape.IsNull() ) &&  fromSubshapeToMainshape )
491     return myListOfIDs;
492   else   if ( ( myMainShape.IsNull() || myGeomShape.IsNull() ) &&  !fromSubshapeToMainshape )
493     return mySelectedIDs;
494
495   QList<int> aList;
496   TopTools_IndexedMapOfShape   aGeomMap;
497   TopTools_IndexedMapOfShape   aMainMap;
498   TopExp::MapShapes(myGeomShape, aGeomMap);
499   TopExp::MapShapes(myMainShape, aMainMap);
500
501   if ( fromSubshapeToMainshape ) { // convert indexes from subshape to mainshape
502     int size = myListOfIDs.size();
503     for (int i = 0; i < size; i++) {
504       TopoDS_Shape aSubShape = aGeomMap.FindKey( myListOfIDs.at(i) );
505       int index = aMainMap.FindIndex( aSubShape );
506       aList.append( index );
507     }
508     myIsNotCorrected = false;
509   } else { // convert indexes from main shape to subshape
510     int size = mySelectedIDs.size();
511     for (int i = 0; i < size; i++) {
512       TopoDS_Shape aSubShape = aMainMap.FindKey( mySelectedIDs.at(i) );
513       int index = aGeomMap.FindIndex( aSubShape );
514       aList.append( index );
515     }
516   }
517
518   return aList;
519 }