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