Salome HOME
Merge from V6_main (04/10/2012)
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_GroupOnShapeDlg.cxx
1 // Copyright (C) 2007-2012  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 //  SMESH SMESHGUI : GUI for SMESH component
21 // File      : SMESHGUI_GroupOnShapeDlg.cxx
22 // Created   : Wed Sep 17 18:36:51 2008
23 // Author    : Edward AGAPOV (eap)
24 // Module    : SMESH
25 // IDL Headers
26 //
27 #include "SMESHGUI_GroupOnShapeDlg.h"
28
29 #include "SMESH_TypeFilter.hxx"
30 #include "SMESHGUI.h"
31 #include "SMESHGUI_Utils.h"
32 #include "SMESHGUI_GEOMGenUtils.h"
33
34 #include <GeometryGUI.h>
35 #include <GEOM_SelectionFilter.h>
36
37 #include <SUIT_Session.h>
38 #include <SUIT_OverrideCursor.h>
39 #include <LightApp_Application.h>
40 #include <LightApp_UpdateFlags.h>
41 #include <SUIT_ResourceMgr.h>
42
43 #include <SALOMEconfig.h>
44 #include CORBA_SERVER_HEADER(SMESH_Mesh)
45 #include CORBA_SERVER_HEADER(SMESH_Group)
46
47 #include <QGroupBox>
48 #include <QLayout>
49 #include <QFrame>
50 #include <QLabel>
51 #include <QPushButton>
52 #include <QListWidget>
53 #include <QLineEdit>
54
55 #define SPACING 6
56 #define MARGIN  11
57
58 enum { _MESH, _ELEM_GEOM, _NODE_GEOM };
59
60 SMESHGUI_GroupOnShapeDlg::SMESHGUI_GroupOnShapeDlg()
61   : SMESHGUI_Dialog( 0, false, true )
62 {
63   QPixmap image (resourceMgr()->loadPixmap("SMESH", tr("ICON_SELECT")));
64
65   // Name
66   //QLabel* nameLabel = new QLabel( tr( "SMESH_NAME" ), mainFrame() );
67   //myGrpNameLine = new QLineEdit( mainFrame() );
68
69   // Mesh
70   QLabel* meshLabel = new QLabel( tr( "SMESH_OBJECT_MESH" ), mainFrame() );
71   myMeshBtn = new QPushButton( mainFrame() );
72   myMeshBtn->setCheckable(true);
73   myMeshBtn->setIcon(image);
74   myMeshLine = new QLineEdit( mainFrame() );
75   myMeshLine->setReadOnly(true);
76
77   // Elem geom
78
79   QGroupBox* elemsGrp = new QGroupBox( tr( "SMESH_ELEMENTS" ), mainFrame() );
80   QLabel* label = new QLabel( tr( "SMESH_GEOM" ), elemsGrp );
81   myElemGeomBtn = new QPushButton( elemsGrp );
82   myElemGeomBtn->setCheckable(true);
83   myElemGeomBtn->setIcon(image);
84   myElemGeomList = new QListWidget( elemsGrp );
85   myElemGeomList->setSelectionMode(QListWidget::NoSelection);
86
87   QGridLayout* elemLay = new QGridLayout(elemsGrp);
88   elemLay->setSpacing( SPACING );
89   elemLay->setMargin( MARGIN );
90   elemLay->setRowStretch( 1, 1 );
91   elemLay->addWidget( label, 0, 0 );
92   elemLay->addWidget( myElemGeomBtn, 0, 1 );
93   elemLay->addWidget( myElemGeomList, 0, 2, 2, 1);
94
95   // Node geom
96
97   QGroupBox* nodesGrp = new QGroupBox( tr( "SMESH_NODES" ), mainFrame() );
98
99   label = new QLabel( tr( "SMESH_GEOM" ), nodesGrp );
100   myNodeGeomBtn = new QPushButton( nodesGrp );
101   myNodeGeomBtn->setCheckable(true);
102   myNodeGeomBtn->setIcon(image);
103   myNodeGeomList = new QListWidget( nodesGrp );
104   myNodeGeomList->setSelectionMode(QListWidget::NoSelection);
105
106   QGridLayout* nodeLay = new QGridLayout(nodesGrp);
107   nodeLay->setSpacing( SPACING );
108   nodeLay->setMargin( MARGIN );
109   nodeLay->setRowStretch( 1, 1 );
110   nodeLay->addWidget( label, 0, 0 );
111   nodeLay->addWidget( myNodeGeomBtn, 0, 1 );
112   nodeLay->addWidget(myNodeGeomList, 0, 2, 2, 1);
113
114   // Fill layout
115   QGridLayout* aLay = new QGridLayout( mainFrame());
116   aLay->setSpacing( SPACING );
117   aLay->setMargin( MARGIN );
118   //aLay->addWidget( nameLabel, 0, 0 );
119   //aLay->addWidget( myGrpNameLine, 0, 2 );
120   aLay->addWidget( meshLabel, 1, 0 );
121   aLay->addWidget( myMeshBtn, 1, 1 );
122   aLay->addWidget( myMeshLine,1, 2 );
123   aLay->addWidget( elemsGrp, 2, 1, 1, 3 );
124   aLay->addWidget( nodesGrp, 3, 1, 1, 3 );
125
126   setWindowTitle( tr( "SMESH_CREATE_GROUP_FROM_GEOM" ) );
127 }
128
129 SMESHGUI_GroupOnShapeDlg::~SMESHGUI_GroupOnShapeDlg()
130 {
131 }
132
133 //================================================================================
134 /*!
135  * \brief slot to enable/diable [Apply]
136  */
137 //================================================================================
138
139 void SMESHGUI_GroupOnShapeDlg::updateButtons()
140 {
141   bool enable =
142     /*!myGrpNameLine->text().isEmpty() &&*/ myElemGeomList->count() + myNodeGeomList->count();
143
144   button(Apply)->setEnabled( enable );
145   button(OK)->setEnabled( enable );
146 }
147
148 //================================================================================
149 /*!
150  * \brief initialization
151  */
152 //================================================================================
153
154 void SMESHGUI_GroupOnShapeDlg::init()
155 {
156   //myGrpNameLine->setText("");
157
158   myMeshBtn->setChecked( true );
159   myMeshLine->setText("");
160
161   myElemGeomBtn->setChecked(false);
162   myElemGeomBtn->setEnabled(false);
163   myElemGeomList->clear();
164   myNodeGeomBtn->setChecked(false);
165   myNodeGeomBtn->setEnabled(false);
166   myNodeGeomList->clear();
167
168   updateButtons();
169 }
170
171 //================================================================================
172 /*!
173  * \brief operation constructor
174  */
175 //================================================================================
176
177 SMESHGUI_GroupOnShapeOp::SMESHGUI_GroupOnShapeOp()
178   : SMESHGUI_SelectionOp(ActorSelection),
179     myDlg( 0 )
180 {
181   myHelpFileName = "create_groups_from_geometry_page.html";
182 }
183
184 SMESHGUI_GroupOnShapeOp::~SMESHGUI_GroupOnShapeOp()
185 {
186   if ( myDlg )
187     delete myDlg;
188 }
189 //================================================================================
190 /*!
191  * \brief Gets dialog of this operation
192   * \retval LightApp_Dialog* - pointer to dialog of this operation
193 */
194 //================================================================================
195
196 LightApp_Dialog* SMESHGUI_GroupOnShapeOp::dlg() const
197 {
198   return myDlg;
199 }
200
201 //================================================================================
202 /*!
203  * \brief return type of mesh group by geom object
204  */
205 //================================================================================
206
207 static SMESH::ElementType elementType(GEOM::GEOM_Object_var& geom)
208 {
209   if ( !geom->_is_nil() ) {
210     switch ( geom->GetShapeType() ) {
211     case GEOM::VERTEX:   return SMESH::NODE;
212     case GEOM::EDGE:     return SMESH::EDGE;
213     case GEOM::WIRE:     return SMESH::EDGE;
214     case GEOM::FACE:     return SMESH::FACE;
215     case GEOM::SHELL:    return SMESH::FACE;
216     case GEOM::SOLID:    return SMESH::VOLUME;
217     case GEOM::COMPSOLID:return SMESH::VOLUME;
218     case GEOM::COMPOUND: break;
219     default:             return SMESH::ALL;
220     }
221     _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
222     GEOM::GEOM_IShapesOperations_var aShapeOp =
223       SMESH::GetGEOMGen()->GetIShapesOperations(aStudy->StudyId());
224
225     if ( geom->GetType() == 37 ) { // geom group
226       GEOM::GEOM_IGroupOperations_var  aGroupOp =
227         SMESH::GetGEOMGen()->GetIGroupOperations(aStudy->StudyId());
228       if ( !aGroupOp->_is_nil() ) {
229         GEOM::GEOM_Object_var mainShape = aGroupOp->GetMainShape( geom );
230         GEOM::ListOfLong_var        ids = aGroupOp->GetObjects( geom );
231         if ( ids->length() && !mainShape->_is_nil() && !aShapeOp->_is_nil() ) {
232           GEOM::GEOM_Object_var member = aShapeOp->GetSubShape( mainShape, ids[0] );
233           return elementType( member );
234         }
235       }
236     }
237     else if ( !aShapeOp->_is_nil() ) { // just a compoud shape
238       GEOM::ListOfLong_var ids = aShapeOp->SubShapeAllIDs( geom, GEOM::SHAPE, false );
239       if ( ids->length() ) {
240         GEOM::GEOM_Object_var member = aShapeOp->GetSubShape( geom, ids[0] );
241         return elementType( member );
242       }
243     }
244   }
245   return SMESH::ALL;
246 }
247
248 //================================================================================
249 /*!
250  * \brief initialization
251  */
252 //================================================================================
253
254 void SMESHGUI_GroupOnShapeOp::init()
255 {
256   myMeshID="";
257   myElemGeoIDs.clear();
258   myNodeGeoIDs.clear();
259
260   myDlg->init();
261   removeCustomFilters();
262   onActivateObject( _MESH ); // install filter
263 }
264
265 //================================================================================
266 /*!
267  * \brief start operation
268  */
269 //================================================================================
270
271 void SMESHGUI_GroupOnShapeOp::startOperation()
272 {
273   if (!myDlg)
274   {
275     myDlg = new SMESHGUI_GroupOnShapeDlg();
276     connect(myDlg->myMeshBtn,     SIGNAL(clicked()), this, SLOT(onButtonClick()));
277     connect(myDlg->myElemGeomBtn, SIGNAL(clicked()), this, SLOT(onButtonClick()));
278     connect(myDlg->myNodeGeomBtn, SIGNAL(clicked()), this, SLOT(onButtonClick()));
279     //connect(myDlg->myGrpNameLine, SIGNAL(textChanged(const QString&)),myDlg,SLOT(updateButtons()));
280   }
281   SMESHGUI_SelectionOp::startOperation();
282
283   init();
284   myDlg->show();
285 }
286
287 //================================================================================
288 /*!
289  * \brief create groups
290  */
291 //================================================================================
292
293 bool SMESHGUI_GroupOnShapeOp::onApply()
294 {
295   SUIT_OverrideCursor aWaitCursor;
296
297   if (isStudyLocked())
298     return false;
299
300   // study
301   _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
302   if ( !aStudy ) return false;
303
304   // mesh
305   _PTR(SObject) meshSO = aStudy->FindObjectID( myMeshID.toLatin1().data() );
306   SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( meshSO );
307   if ( mesh->_is_nil() ) return false;
308
309   // names of all existing groups
310 //   QStringList groupNames;
311 //   QString givenName = myDlg->myGrpNameLine->text();
312 //   if ( !givenName.isEmpty() ) {
313 //     SMESH::ListOfGroups_var groups = mesh->GetGroups();
314 //     for ( int i = 0; i < groups->length(); ++i ) {
315 //       CORBA::String_var name = groups[i]->GetName();
316 //       groupNames.append( name.in() );
317 //     }
318 //   }
319
320   // create groups
321   SMESH::SMESH_GroupOnGeom_var group;
322   QStringList anEntryList;
323   for ( int isNode = 0; isNode < 2; ++isNode ) // elems and then nodes
324   {
325     QStringList::iterator geomID = isNode ? myNodeGeoIDs.begin() : myElemGeoIDs.begin();
326     QStringList::iterator geomEnd = isNode ? myNodeGeoIDs.end() : myElemGeoIDs.end();
327
328     for ( int i = 0; geomID != geomEnd; ++geomID, ++i )
329     {
330       // selected geom
331       _PTR(SObject) geomSO = aStudy->FindObjectID( geomID->toLatin1().data() );
332       GEOM::GEOM_Object_var geom = SMESH::SObjectToInterface<GEOM::GEOM_Object>(geomSO);
333       if ( geom->_is_nil() ) continue;
334
335       // group type
336       SMESH::ElementType elemType = isNode ? SMESH::NODE : elementType( geom );
337       if ( elemType == SMESH::ALL )
338         continue;
339
340       // make a unique name
341       QString name =
342         isNode ? myDlg->myNodeGeomList->item(i)->text() : myDlg->myElemGeomList->item(i)->text();
343 //       int nb = 1;
344 //       QString name = myDlg->myGrpNameLine->text() + "_" + QString::number(nb);
345 //       while ( groupNames.contains( name ))
346 //         name = myDlg->myGrpNameLine->text() + "_" + QString::number(++nb);
347 //       groupNames.append( name );
348
349       //printf( "apply() %s %s\n", (*geomID).latin1(), name.latin1() );
350       group = mesh->CreateGroupFromGEOM( elemType, name.toLatin1().data(), geom );
351       if( !group->_is_nil() )
352         if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( group ) )
353           anEntryList.append( aSObject->GetID().c_str() );
354     }
355   }
356   SMESHGUI::Modified();
357
358   update( UF_ObjBrowser | UF_Model );
359
360   // Re-init controls to create the next group
361   myElemGeoIDs.clear();
362   myNodeGeoIDs.clear();
363   removeCustomFilters();
364   myDlg->myNodeGeomList->clear();
365   myDlg->myElemGeomList->clear();
366   myDlg->myElemGeomBtn->setChecked(false); 
367   myDlg->myNodeGeomBtn->setChecked(false);
368   myDlg->updateButtons();
369
370   if( LightApp_Application* anApp =
371       dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() ) )
372     anApp->browseObjects( anEntryList, isApplyAndClose() );
373
374   return !group->_is_nil();
375 }
376
377 //================================================================================
378 /*!
379  * \brief slot connected to selection buttons
380  */
381 //================================================================================
382
383 void SMESHGUI_GroupOnShapeOp::onButtonClick()
384 {
385   removeCustomFilters();
386
387   if ( sender() == myDlg->myMeshBtn && myDlg->myMeshBtn->isChecked() )
388   {
389     myDlg->myElemGeomBtn->setChecked(false);
390     myDlg->myNodeGeomBtn->setChecked(false);
391     onActivateObject( _MESH ); // install filter
392   }
393   else if ( sender() == myDlg->myElemGeomBtn && myDlg->myElemGeomBtn->isChecked() )
394   {
395     myDlg->myMeshBtn->setChecked(false);
396     myDlg->myNodeGeomBtn->setChecked(false);
397     onActivateObject( _ELEM_GEOM ); // install filter
398   }
399   else if ( sender() == myDlg->myNodeGeomBtn && myDlg->myNodeGeomBtn->isChecked() )
400   {
401     myDlg->myMeshBtn->setChecked(false);
402     myDlg->myElemGeomBtn->setChecked(false);
403     onActivateObject( _NODE_GEOM ); // install filter
404   }
405   //selectionDone();
406 }
407
408 //================================================================================
409 /*!
410  * \brief Creates selection filter
411   * \param theId - identifier of current selection widget
412   * \retval SUIT_SelectionFilter* - pointer to the created filter or null
413  *
414  * Creates selection filter in accordance with identifier of current selection widget
415  */
416 //================================================================================
417 SUIT_SelectionFilter* SMESHGUI_GroupOnShapeOp::createFilter( const int theId ) const
418 {
419   if ( theId == _ELEM_GEOM || theId == _NODE_GEOM )
420     return new GEOM_SelectionFilter( (SalomeApp_Study*)study(), true );
421   else if ( theId == _MESH )
422     return new SMESH_TypeFilter( MESH );
423   else
424     return ( SUIT_SelectionFilter*) 0;
425 }
426 //================================================================================
427 /*!
428  * \brief Updates dialog's look and feel
429  *
430  * Virtual method redefined from the base class updates dialog's look and feel
431  */
432 //================================================================================
433 void SMESHGUI_GroupOnShapeOp::selectionDone()
434 {
435   QStringList names, ids;
436   LightApp_Dialog::TypesList types;
437   selected( names, types, ids );
438   int nbSelected = names.size();
439
440   if ( myDlg->myMeshBtn->isChecked() ) // mesh selected
441   {
442     myDlg->myMeshLine->setText("");
443     myMeshID = "";
444     if ( nbSelected == 1 ) {
445       myDlg->myMeshLine->setText( names.front() );
446       myMeshID = ids.front();
447     }
448     myDlg->myElemGeomList->clear();
449     myDlg->myElemGeomBtn->setEnabled( nbSelected == 1 );
450     myDlg->myNodeGeomList->clear();
451     myDlg->myNodeGeomBtn->setEnabled( nbSelected == 1 );
452     myDlg->myElemGeomBtn->click();
453     return;
454   }
455
456   // Filter off inappropriate shapes
457
458   QStringList goodNames, goodIds;
459   if (nbSelected > 0) {
460     // study
461     if (_PTR(Study) aStudy = SMESH::GetActiveStudyDocument()) {
462       // mesh
463       if (_PTR(SObject)  meshSO = aStudy->FindObjectID( myMeshID.toLatin1().data() )) {
464         // shape to mesh
465         _PTR(SObject) anObj, shapeToMesh;
466         if (meshSO->FindSubObject(1, anObj) && anObj->ReferencedObject(shapeToMesh)) {
467           // loop on selected
468           QStringList::iterator name = names.begin(), id = ids.begin(), idEnd = ids.end();
469           for (; id != idEnd; ++id, ++name ) {
470             // shape SO
471             if (_PTR(SObject) shapeSO = aStudy->FindObjectID( id->toLatin1().data() )) {
472             // check if shape SO is a child of shape to mesh 
473               while ( shapeSO && shapeSO->GetID() != shapeToMesh->GetID() )
474                 if  ( shapeSO->Depth() < 2 )
475                   shapeSO.reset();
476                 else
477                   shapeSO = shapeSO->GetFather();
478               if ( shapeSO ) {
479                 //printf( "selectionDone() %s %s\n", (*id).latin1(), (*name).latin1() );
480                 if ( !goodIds.contains( *id )) {
481                   goodIds.append( *id );
482                   goodNames.append( *name );
483                 }
484               }
485             }
486           }
487         }
488       }
489     }
490   }
491
492   if ( myDlg->myElemGeomBtn->isChecked() ) // elem geomerty selection
493   {
494     myDlg->myElemGeomList->clear();
495     myDlg->myElemGeomList->addItems( goodNames );
496     myElemGeoIDs = goodIds;
497   }
498   else if ( myDlg->myNodeGeomBtn->isChecked() ) // Node geomerty selection
499   {
500     myDlg->myNodeGeomList->clear();
501     myDlg->myNodeGeomList->addItems( goodNames );
502     myNodeGeoIDs = goodIds;
503   }
504
505   // enable/diable Apply, which can change at selection
506   myDlg->updateButtons();
507 }