Salome HOME
0019970: create groups automatically
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_GroupOnShapeDlg.cxx
1 //  SMESH SMESHGUI : GUI for SMESH component
2 //
3 //  Copyright (C) 2003  CEA
4 // 
5 //  This library is free software; you can redistribute it and/or 
6 //  modify it under the terms of the GNU Lesser General Public 
7 //  License as published by the Free Software Foundation; either 
8 //  version 2.1 of the License. 
9 // 
10 //  This library is distributed in the hope that it will be useful, 
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
13 //  Lesser General Public License for more details. 
14 // 
15 //  You should have received a copy of the GNU Lesser General Public 
16 //  License along with this library; if not, write to the Free Software 
17 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
18 // 
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 //
21 //
22 //
23 // File      : SMESHGUI_GroupOnShapeDlg.cxx
24 // Created   : Wed Sep 17 18:36:51 2008
25 // Author    : Edward AGAPOV (eap)
26 // Module    : SMESH
27
28
29 // IDL Headers
30 #include "SMESHGUI_GroupOnShapeDlg.h"
31
32 #include "SMESH_TypeFilter.hxx"
33 #include "SMESHGUI_Utils.h"
34 #include "SMESHGUI_GEOMGenUtils.h"
35
36 #include <GeometryGUI.h>
37 #include <GEOM_SelectionFilter.h>
38
39 #include <SUIT_Session.h>
40 #include <SUIT_OverrideCursor.h>
41 #include <LightApp_UpdateFlags.h>
42
43 #include <SALOMEconfig.h>
44 #include CORBA_SERVER_HEADER(SMESH_Mesh)
45 #include CORBA_SERVER_HEADER(SMESH_Group)
46
47 #include <qgroupbox.h>
48 #include <qlayout.h>
49 #include <qframe.h>
50 #include <qlabel.h>
51 #include <qpushbutton.h>
52 #include <qlistbox.h>
53 #include <qlineedit.h>
54
55 enum { _MESH, _ELEM_GEOM, _NODE_GEOM };
56
57 SMESHGUI_GroupOnShapeDlg::SMESHGUI_GroupOnShapeDlg()
58   : SMESHGUI_Dialog( 0, false, true )
59 {
60   QPixmap image (resourceMgr()->loadPixmap("SMESH", tr("ICON_SELECT")));
61
62   QGroupBox* aGrp = new QGroupBox( 3, Qt::Horizontal, mainFrame() );
63   aGrp->setFrameStyle( QFrame::NoFrame );
64   aGrp->setInsideMargin( 0 );
65
66   // Name
67   //new QLabel( tr( "SMESH_NAME" ), aGrp ); new QLabel( "", aGrp );
68   //myGrpNameLine = new QLineEdit( aGrp, "myGrpNameLine" );
69
70   // Mesh
71   new QLabel( tr( "SMESH_OBJECT_MESH" ), aGrp );
72   myMeshBtn = new QPushButton( aGrp, "myMeshBtn");
73   myMeshBtn->setToggleButton(true);
74   myMeshBtn->setPixmap(image);
75   myMeshLine = new QLineEdit( aGrp, "myMeshLine" );
76   myMeshLine->setReadOnly(true);
77
78   // Elem geom
79
80   QGroupBox* elemsGrp = new QGroupBox( 1, Qt::Horizontal, tr( "SMESH_ELEMENTS" ), mainFrame() );
81   QFrame* elemFr = new QFrame(elemsGrp, "elemFr");
82
83   QLabel* label = new QLabel( tr( "SMESH_OBJECT_GEOM" ), elemFr );
84   myElemGeomBtn = new QPushButton( elemFr, "myElemGeomBtn");
85   myElemGeomBtn->setToggleButton(true);
86   myElemGeomBtn->setPixmap(image);
87   myElemGeomList = new QListBox( elemFr, "myElemGeomList" );
88   myElemGeomList->setSelectionMode(QListBox::NoSelection);
89
90   QGridLayout* elemLay = new QGridLayout(elemFr, 2, 3);
91   elemLay->setSpacing(6);
92   elemLay->setAutoAdd(false);
93   elemLay->setRowStretch( 1, 1 );
94   elemLay->addWidget( label, 0, 0 );
95   elemLay->addWidget( myElemGeomBtn, 0, 1 );
96   elemLay->addMultiCellWidget(myElemGeomList, 0, 1, 2, 2);
97
98   // Node geom
99
100   QGroupBox* nodesGrp = new QGroupBox( 1, Qt::Horizontal, tr( "SMESH_NODES" ), mainFrame() );
101   QFrame* nodeFr = new QFrame(nodesGrp, "nodeFr");
102
103   label = new QLabel( tr( "SMESH_OBJECT_GEOM" ), nodeFr );
104   myNodeGeomBtn = new QPushButton( nodeFr, "myNodeGeomBtn");
105   myNodeGeomBtn->setToggleButton(true);
106   myNodeGeomBtn->setPixmap(image);
107   myNodeGeomList = new QListBox( nodeFr, "myNodeGeomList" );
108   myNodeGeomList->setSelectionMode(QListBox::NoSelection);
109
110   QGridLayout* nodeLay = new QGridLayout(nodeFr, 2, 3);
111   nodeLay->setSpacing(6);
112   nodeLay->setAutoAdd(false);
113   nodeLay->setRowStretch( 1, 1 );
114   nodeLay->addWidget( label, 0, 0 );
115   nodeLay->addWidget( myNodeGeomBtn, 0, 1 );
116   nodeLay->addMultiCellWidget(myNodeGeomList, 0, 1, 2, 2);
117
118   // Fill layout
119   QVBoxLayout* aLay = new QVBoxLayout( mainFrame(), 0, 5 );
120   aLay->addWidget( aGrp );
121   aLay->addWidget( elemsGrp );
122   aLay->addWidget( nodesGrp );
123
124   setCaption( tr( "SMESH_CREATE_GROUP_FROM_GEOM" ) );
125 }
126
127 //================================================================================
128 /*!
129  * \brief slot to enable/diable [Apply]
130  */
131 //================================================================================
132
133 void SMESHGUI_GroupOnShapeDlg::updateButtons()
134 {
135   bool enable =
136     /*!myGrpNameLine->text().isEmpty() &&*/ myElemGeomList->count() + myNodeGeomList->count();
137
138   button(Apply)->setEnabled( enable );
139   button(OK)->setEnabled( enable );
140 }
141
142 //================================================================================
143 /*!
144  * \brief initialization
145  */
146 //================================================================================
147
148 void SMESHGUI_GroupOnShapeDlg::init()
149 {
150   //myGrpNameLine->setText("");
151
152   myMeshBtn->setOn( true );
153   myMeshLine->setText("");
154
155   myElemGeomBtn->setOn(false);
156   myElemGeomBtn->setEnabled(false);
157   myElemGeomList->clear();
158   myNodeGeomBtn->setOn(false);
159   myNodeGeomBtn->setEnabled(false);
160   myNodeGeomList->clear();
161
162   updateButtons();
163 }
164
165 //================================================================================
166 /*!
167  * \brief operation constructor
168  */
169 //================================================================================
170
171 SMESHGUI_GroupOnShapeOp::SMESHGUI_GroupOnShapeOp()
172   : SMESHGUI_SelectionOp(ActorSelection),
173     myDlg( 0 )
174 {
175   myHelpFileName = "creating_groups_page.html";
176 }
177
178 SMESHGUI_GroupOnShapeOp::~SMESHGUI_GroupOnShapeOp()
179 {
180   if ( myDlg )
181     delete myDlg;
182 }
183 //================================================================================
184 /*!
185  * \brief Gets dialog of this operation
186   * \retval LightApp_Dialog* - pointer to dialog of this operation
187 */
188 //================================================================================
189
190 LightApp_Dialog* SMESHGUI_GroupOnShapeOp::dlg() const
191 {
192   return myDlg;
193 }
194
195 //================================================================================
196 /*!
197  * \brief return type of mesh group by geom object
198  */
199 //================================================================================
200
201 static SMESH::ElementType elementType(GEOM::GEOM_Object_var& geom)
202 {
203   if ( !geom->_is_nil() ) {
204     switch ( geom->GetShapeType() ) {
205     case GEOM::VERTEX:   return SMESH::NODE;
206     case GEOM::EDGE:     return SMESH::EDGE;
207     case GEOM::WIRE:     return SMESH::EDGE;
208     case GEOM::FACE:     return SMESH::FACE;
209     case GEOM::SHELL:    return SMESH::FACE;
210     case GEOM::SOLID:    return SMESH::VOLUME;
211     case GEOM::COMPSOLID:return SMESH::VOLUME;
212     case GEOM::COMPOUND: break;
213     default:             return SMESH::ALL;
214     }
215     _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
216     GEOM::GEOM_IShapesOperations_var aShapeOp =
217       SMESH::GetGEOMGen()->GetIShapesOperations(aStudy->StudyId());
218
219     if ( geom->GetType() == 37 ) { // geom group
220       GEOM::GEOM_IGroupOperations_var  aGroupOp =
221         SMESH::GetGEOMGen()->GetIGroupOperations(aStudy->StudyId());
222       if ( !aGroupOp->_is_nil() ) {
223         GEOM::GEOM_Object_var mainShape = aGroupOp->GetMainShape( geom );
224         GEOM::ListOfLong_var        ids = aGroupOp->GetObjects( geom );
225         if ( ids->length() && !mainShape->_is_nil() && !aShapeOp->_is_nil() ) {
226           GEOM::GEOM_Object_var member = aShapeOp->GetSubShape( mainShape, ids[0] );
227           return elementType( member );
228         }
229       }
230     }
231     else if ( !aShapeOp->_is_nil() ) { // just a compoud shape
232       GEOM::ListOfLong_var ids = aShapeOp->SubShapeAllIDs( geom, GEOM::SHAPE, false );
233       if ( ids->length() ) {
234         GEOM::GEOM_Object_var member = aShapeOp->GetSubShape( geom, ids[0] );
235         return elementType( member );
236       }
237     }
238   }
239   return SMESH::ALL;
240 }
241
242 //================================================================================
243 /*!
244  * \brief initialization
245  */
246 //================================================================================
247
248 void SMESHGUI_GroupOnShapeOp::init()
249 {
250   myMeshID="";
251   myElemGeoIDs.clear();
252   myNodeGeoIDs.clear();
253
254   myDlg->init();
255   removeCustomFilters();
256   onActivateObject( _MESH ); // install filter
257 }
258
259 //================================================================================
260 /*!
261  * \brief start operation
262  */
263 //================================================================================
264
265 void SMESHGUI_GroupOnShapeOp::startOperation()
266 {
267   if (!myDlg)
268   {
269     myDlg = new SMESHGUI_GroupOnShapeDlg();
270     connect(myDlg->myMeshBtn,     SIGNAL(clicked()), this, SLOT(onButtonClick()));
271     connect(myDlg->myElemGeomBtn, SIGNAL(clicked()), this, SLOT(onButtonClick()));
272     connect(myDlg->myNodeGeomBtn, SIGNAL(clicked()), this, SLOT(onButtonClick()));
273     //connect(myDlg->myGrpNameLine, SIGNAL(textChanged(const QString&)),myDlg,SLOT(updateButtons()));
274   }
275   SMESHGUI_SelectionOp::startOperation();
276
277   init();
278   myDlg->show();
279 }
280
281 //================================================================================
282 /*!
283  * \brief create groups
284  */
285 //================================================================================
286
287 bool SMESHGUI_GroupOnShapeOp::onApply()
288 {
289   SUIT_OverrideCursor aWaitCursor;
290
291   if (isStudyLocked())
292     return false;
293
294   // study
295   _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
296   if ( !aStudy ) return false;
297
298   // mesh
299   _PTR(SObject)       meshSO = aStudy->FindObjectID( myMeshID );
300   SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( meshSO );
301   if ( mesh->_is_nil() ) return false;
302
303   // names of all existing groups
304 //   QStringList groupNames;
305 //   QString givenName = myDlg->myGrpNameLine->text();
306 //   if ( !givenName.isEmpty() ) {
307 //     SMESH::ListOfGroups_var groups = mesh->GetGroups();
308 //     for ( int i = 0; i < groups->length(); ++i ) {
309 //       CORBA::String_var name = groups[i]->GetName();
310 //       groupNames.append( name.in() );
311 //     }
312 //   }
313
314   // create groups
315   SMESH::SMESH_GroupOnGeom_var group;
316   for ( int isNode = 0; isNode < 2; ++isNode ) // elems and then nodes
317   {
318     QStringList::iterator geomID = isNode ? myNodeGeoIDs.begin() : myElemGeoIDs.begin();
319     QStringList::iterator geomEnd = isNode ? myNodeGeoIDs.end() : myElemGeoIDs.end();
320
321     for (int i = 0 ; geomID != geomEnd; ++geomID, ++i )
322     {
323       // selected geom
324       _PTR(SObject) geomSO = aStudy->FindObjectID( *geomID );
325       GEOM::GEOM_Object_var geom = SMESH::SObjectToInterface<GEOM::GEOM_Object>(geomSO);
326       if ( geom->_is_nil() ) continue;
327
328       // group type
329       SMESH::ElementType elemType = isNode ? SMESH::NODE : elementType( geom );
330       if ( elemType == SMESH::ALL )
331         continue;
332
333       // group name
334       QString name;
335       //if ( givenName.isEmpty() ) { // use shape name
336         name = isNode ? myDlg->myNodeGeomList->text(i) : myDlg->myElemGeomList->text(i);
337 //       }
338 //       else { // make a unique name
339 //         name = givenName;
340 //         int nb = 0;
341 //         if ( myNodeGeoIDs.size() + myElemGeoIDs.size() > 1 )
342 //           name += "_" + QString::number(++nb);
343 //         while ( groupNames.contains( name ))
344 //           name = givenName + "_" + QString::number(++nb);
345 //         groupNames.append( name );
346 //       }
347       //printf( "apply() %s %s\n", (*geomID).latin1(), name.latin1() );
348       group = mesh->CreateGroupFromGEOM( elemType, name, geom );
349     }
350   }
351   update( UF_ObjBrowser | UF_Model );
352
353   init();
354
355   return !group->_is_nil();
356 }
357
358 //================================================================================
359 /*!
360  * \brief slot connected to selection buttons
361  */
362 //================================================================================
363
364 void SMESHGUI_GroupOnShapeOp::onButtonClick()
365 {
366   removeCustomFilters();
367
368   if ( sender() == myDlg->myMeshBtn && myDlg->myMeshBtn->isOn() )
369   {
370     myDlg->myElemGeomBtn->setOn(false);
371     myDlg->myNodeGeomBtn->setOn(false);
372     onActivateObject( _MESH ); // install filter
373   }
374   else if ( sender() == myDlg->myElemGeomBtn && myDlg->myElemGeomBtn->isOn() )
375   {
376     myDlg->myMeshBtn->setOn(false);
377     myDlg->myNodeGeomBtn->setOn(false);
378     onActivateObject( _ELEM_GEOM ); // install filter
379   }
380   else if ( sender() == myDlg->myNodeGeomBtn && myDlg->myNodeGeomBtn->isOn() )
381   {
382     myDlg->myMeshBtn->setOn(false);
383     myDlg->myElemGeomBtn->setOn(false);
384     onActivateObject( _NODE_GEOM ); // install filter
385   }
386   //selectionDone();
387 }
388
389 //================================================================================
390 /*!
391  * \brief Creates selection filter
392   * \param theId - identifier of current selection widget
393   * \retval SUIT_SelectionFilter* - pointer to the created filter or null
394  *
395  * Creates selection filter in accordance with identifier of current selection widget
396  */
397 //================================================================================
398 SUIT_SelectionFilter* SMESHGUI_GroupOnShapeOp::createFilter( const int theId ) const
399 {
400   if ( theId == _ELEM_GEOM || theId == _NODE_GEOM )
401     return new GEOM_SelectionFilter( (SalomeApp_Study*)study(), true );
402   else if ( theId == _MESH )
403     return new SMESH_TypeFilter( MESH );
404   else
405     return ( SUIT_SelectionFilter*) 0;
406 }
407 //================================================================================
408 /*!
409  * \brief Updates dialog's look and feel
410  *
411  * Virtual method redefined from the base class updates dialog's look and feel
412  */
413 //================================================================================
414 void SMESHGUI_GroupOnShapeOp::selectionDone()
415 {
416   QStringList names, ids;
417   LightApp_Dialog::TypesList types;
418   selected( names, types, ids );
419   int nbSelected = names.size();
420
421   if ( myDlg->myMeshBtn->isOn() ) // mesh selected
422   {
423     myDlg->myMeshLine->setText("");
424     myMeshID = "";
425     if ( nbSelected == 1 ) {
426       myDlg->myMeshLine->setText( names.front() );
427       myMeshID = ids.front();
428     }
429     myDlg->myElemGeomList->clear();
430     myDlg->myElemGeomBtn->setEnabled( nbSelected == 1 );
431     myDlg->myNodeGeomList->clear();
432     myDlg->myNodeGeomBtn->setEnabled( nbSelected == 1 );
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 )) {
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 )) {
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->isOn() ) // elem geomerty selection
473   {
474     myDlg->myElemGeomList->clear();
475     myDlg->myElemGeomList->insertStringList( goodNames );
476     myElemGeoIDs = goodIds;
477   }
478   else if ( myDlg->myNodeGeomBtn->isOn() ) // Node geomerty selection
479   {
480     myDlg->myNodeGeomList->clear();
481     myDlg->myNodeGeomList->insertStringList( goodNames );
482     myNodeGeoIDs = goodIds;
483   }
484
485   // enable/diable Apply, which can change at selection
486   myDlg->updateButtons();
487 }