Salome HOME
23173: EDF 11552 - Problem using Add 0D element function
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_Add0DElemsOnAllNodesDlg.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // SMESH SMESHGUI : GUI for SMESH component
24 // File      : SMESHGUI_Add0DElemsOnAllNodesDlg.cxx
25 // Created   : Fri Oct 19 15:51:24 2012
26 // Author    : Edward AGAPOV (eap)
27
28 #include "SMESHGUI_Add0DElemsOnAllNodesDlg.h"
29
30 #include "SMESHGUI.h"
31 #include "SMESHGUI_FilterDlg.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_Utils.h"
34 #include "SMESHGUI_VTKUtils.h"
35 #include "SMESH_LogicalFilter.hxx"
36 #include "SMESH_TypeFilter.hxx"
37
38 #include <LightApp_SelectionMgr.h>
39 #include <SALOME_ListIO.hxx>
40 #include <SUIT_MessageBox.h>
41 #include <SVTK_Selector.h>
42 #include <SalomeApp_Tools.h>
43
44 // Qt includes
45 #include <QButtonGroup>
46 #include <QCheckBox>
47 #include <QComboBox>
48 #include <QFrame>
49 #include <QGridLayout>
50 #include <QGroupBox>
51 #include <QHBoxLayout>
52 #include <QLabel>
53 #include <QLineEdit>
54 #include <QPushButton>
55 #include <QRadioButton>
56
57 #include <SALOMEconfig.h>
58 #include CORBA_SERVER_HEADER(SMESH_Mesh)
59 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
60
61
62 #define SPACING 6
63 #define MARGIN  11
64
65 enum { SEL_OBJECT, SEL_ELEMENTS, SEL_NODES };
66
67 //================================================================================
68 /*!
69  * \brief Dialog Constructor
70  */
71 //================================================================================
72
73 SMESHGUI_Add0DElemsOnAllNodesDlg::SMESHGUI_Add0DElemsOnAllNodesDlg()
74   : SMESHGUI_Dialog( 0, false, true ),
75     myIDValidator( this )
76 {
77   setWindowTitle( tr( "CAPTION" ) );
78
79   // Seletction type radio buttons
80
81   QGroupBox* selTypeGrBox = new QGroupBox( mainFrame() );
82   //
83   QRadioButton*    objBtn = new QRadioButton( tr( "SMESH_SUBMESH_GROUP"),selTypeGrBox );
84   QRadioButton*   elemBtn = new QRadioButton( tr( "SMESH_ELEMENTS" ),selTypeGrBox );
85   QRadioButton*   nodeBtn = new QRadioButton( tr( "SMESH_NODES" ),selTypeGrBox );
86   //
87   QHBoxLayout* selTypeLay = new QHBoxLayout( selTypeGrBox );
88   selTypeLay->setMargin(MARGIN);
89   selTypeLay->setSpacing(SPACING);
90   selTypeLay->addWidget( objBtn  );
91   selTypeLay->addWidget( elemBtn );
92   selTypeLay->addWidget( nodeBtn );
93   objBtn->setChecked(true);
94   //
95   mySelTypeBtnGrp         = new QButtonGroup( mainFrame() );
96   mySelTypeBtnGrp->addButton( objBtn , SEL_OBJECT );
97   mySelTypeBtnGrp->addButton( elemBtn, SEL_ELEMENTS );
98   mySelTypeBtnGrp->addButton( nodeBtn, SEL_NODES );
99
100   // Label, Select Btn, LineEdit, Filter Btn
101
102   setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
103   createObject( tr( "SMESH_NAME" ), mainFrame(), 0 );
104
105   myFilterBtn = new QPushButton( tr( "SMESH_BUT_FILTER" ), mainFrame() );
106
107   // List of groups
108
109   myGroupBox = new QGroupBox( tr( "SMESH_ADD_TO_GROUP" ), mainFrame() );
110   myGroupBox->setCheckable( true );
111
112   myGroupLabel = new QLabel( tr( "SMESH_GROUP" ), myGroupBox );
113   myGroupListCmBox = new QComboBox( myGroupBox );
114   myGroupListCmBox->setEditable( true );
115   myGroupListCmBox->setInsertPolicy( QComboBox::NoInsert );
116
117   QHBoxLayout* groupsLayout = new QHBoxLayout( myGroupBox );
118   groupsLayout->setSpacing(SPACING);
119   groupsLayout->setMargin(MARGIN);
120   groupsLayout->addWidget( myGroupLabel );
121   groupsLayout->addWidget( myGroupListCmBox, 1 );
122
123   // Main layout
124
125   QGridLayout* aLay = new QGridLayout( mainFrame() );
126   aLay->setMargin(MARGIN);
127   aLay->setSpacing(SPACING);
128   //
129   aLay->addWidget( selTypeGrBox,          0, 0, 1, 5  );
130   //
131   aLay->addWidget( objectWg( 0, Label  ), 1, 0 );
132   aLay->addWidget( objectWg( 0, Btn    ), 1, 1 );
133   aLay->addWidget( objectWg( 0, Control), 1, 2, 1, 2 );
134   aLay->addWidget( myFilterBtn,           1, 4 );
135   //
136   aLay->addWidget( myGroupBox,            2, 0, 1, 5 );
137
138   // Signals
139
140   connect( myGroupBox,      SIGNAL( toggled( bool )),     SLOT( onGroupChecked() ));
141   connect( mySelTypeBtnGrp, SIGNAL( buttonClicked(int) ), SLOT( onSelTypeChange(int)));
142
143   onSelTypeChange( SEL_OBJECT );
144 }
145
146 //================================================================================
147 /*!
148  * \brief SLOT to enable/disable groups
149  */
150 //================================================================================
151
152 void SMESHGUI_Add0DElemsOnAllNodesDlg::onGroupChecked( bool on )
153 {
154   myGroupLabel->setEnabled( on );
155   myGroupListCmBox->setEnabled( on );
156 }
157
158 //================================================================================
159 /*!
160  * \brief SLOT to enable/disable groups
161  */
162 //================================================================================
163
164 void SMESHGUI_Add0DElemsOnAllNodesDlg::onSelTypeChange( int selType )
165 {
166   setNameIndication( 0, selType == SEL_OBJECT ? OneName : ListOfNames );
167   setReadOnly      ( 0, selType == SEL_OBJECT );
168
169   QLabel* label = qobject_cast< QLabel* >( objectWg(0, Label ));
170   switch( selType ) {
171   case SEL_OBJECT:   label->setText( tr("SMESH_NAME")); break;
172   case SEL_ELEMENTS: label->setText( tr("ELEMENT_IDS")); break;
173   case SEL_NODES:    label->setText( tr("NODE_IDS")); break;
174   default:;
175   }
176   QLineEdit* lineEdit = qobject_cast< QLineEdit* >( objectWg(0, Control ));
177   lineEdit->setText("");
178   lineEdit->setValidator( selType == SEL_OBJECT ? 0 : & myIDValidator );
179
180   myFilterBtn->setEnabled( selType != SEL_OBJECT );
181
182   emit selTypeChanged( selType );
183 }
184
185 //================================================================================
186 /*!
187  * \brief Return type of selected object: [SEL_OBJECT, SEL_ELEMENTS, SEL_NODES]
188  */
189 //================================================================================
190
191 int SMESHGUI_Add0DElemsOnAllNodesDlg::getSelectionType() const
192 {
193   return mySelTypeBtnGrp->checkedId();
194 }
195
196 //================================================================================
197 /*!
198  * \brief Checks consistency of data
199  */
200 //================================================================================
201
202 bool SMESHGUI_Add0DElemsOnAllNodesDlg::isValid()
203 {
204   if( myGroupBox->isChecked() && myGroupListCmBox->currentText().isEmpty() ) {
205     SUIT_MessageBox::warning( this, tr( "SMESH_WRN_WARNING" ), tr( "GROUP_NAME_IS_EMPTY" ) );
206     return false;
207   }
208   return true;
209 }
210
211 //================================================================================
212 /*!
213  * \brief Operation Constructor
214  */
215 //================================================================================
216
217 SMESHGUI_Add0DElemsOnAllNodesOp::SMESHGUI_Add0DElemsOnAllNodesOp()
218   :SMESHGUI_SelectionOp(),
219    myDlg( new SMESHGUI_Add0DElemsOnAllNodesDlg ),
220    myFilterDlg( 0 )
221 {
222   myHelpFileName = "adding_nodes_and_elements_page.html#adding_0delems_on_all_nodes_anchor";
223
224   connect( myDlg,              SIGNAL( selTypeChanged(int) ), SLOT( onSelTypeChange(int)));
225   connect( myDlg->myFilterBtn, SIGNAL( clicked()),            SLOT( onSetFilter() ));
226   connect( myDlg->myGroupBox,  SIGNAL( clicked(bool)),        SLOT( updateButtons() ));
227 }
228
229 //================================================================================
230 /*!
231  * \brief Destructor
232  */
233 //================================================================================
234
235 SMESHGUI_Add0DElemsOnAllNodesOp::~SMESHGUI_Add0DElemsOnAllNodesOp()
236 {
237   if ( myFilterDlg ) {
238     myFilterDlg->setParent( 0 );
239     delete myFilterDlg;
240     myFilterDlg = 0;
241   }
242 }
243
244 //================================================================================
245 /*!
246  * \brief Start
247  */
248 //================================================================================
249
250 void SMESHGUI_Add0DElemsOnAllNodesOp::startOperation()
251 {
252   SMESHGUI_SelectionOp::startOperation();
253
254   myDlg->myGroupBox->setChecked( false );
255   myDlg->activateObject( 0 );
256   myDlg->show();
257
258   selectionDone();
259 }
260
261 //================================================================================
262 /*!
263  * \brief Treat changed selection
264  */
265 //================================================================================
266
267 void SMESHGUI_Add0DElemsOnAllNodesOp::selectionDone()
268 {
269   if (myFilterDlg && myFilterDlg->isVisible()) return; // filter dgl active
270   if (!myDlg->myGroupBox->isEnabled())         return; // inactive
271
272   myIO.Nullify();
273   myDlg->setObjectText( 0, "");
274   updateButtons();
275
276   SALOME_ListIO aList;
277   selectionMgr()->selectedObjects( aList );
278   if ( aList.Extent() == 1 )
279     myIO = aList.First();
280   else
281     return;
282
283   QString ids;
284   switch ( myDlg->getSelectionType() ) {
285   case SEL_OBJECT:
286     SMESHGUI_SelectionOp::selectionDone();
287     break;
288   case SEL_ELEMENTS:
289     SMESH::GetNameOfSelectedElements( selector(), myIO, ids );
290     myDlg->setObjectText( 0, ids );
291     break;
292   case SEL_NODES:
293     SMESH::GetNameOfSelectedNodes( selector(), myIO, ids );
294     myDlg->setObjectText( 0, ids );
295     break;
296   default:;
297   }
298
299   // fill the list of existing groups
300   myDlg->myGroupListCmBox->clear();
301   myDlg->myGroupListCmBox->addItem( QString() );
302   if ( !myIO.IsNull() && myIO->hasEntry())
303   {
304     SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
305     _PTR(SObject)       meshSO = SMESH::ObjectToSObject( mesh );
306     _PTR(SObject) group0DRoot;
307     if ( meshSO && meshSO->FindSubObject( SMESH::Tag_0DElementsGroups, group0DRoot ))
308     {
309       _PTR(Study)              aStudy = SMESH::GetActiveStudyDocument();
310       _PTR(ChildIterator) group0DIter = aStudy->NewChildIterator( group0DRoot );
311       for ( ; group0DIter->More(); group0DIter->Next() )
312       {
313         _PTR(SObject) groupSO = group0DIter->Value();
314         std::string groupName = groupSO->GetName();
315         if ( !groupName.empty() )
316           myDlg->myGroupListCmBox->addItem( groupName.c_str() );
317       }
318     }
319     // enable buttons
320     updateButtons();
321   }
322 }
323
324 //=======================================================================
325 //function : updateButtons
326 //purpose  : enable [Apply]
327 //=======================================================================
328
329 void SMESHGUI_Add0DElemsOnAllNodesOp::updateButtons()
330 {
331   bool ok = false;
332
333   if (( !myIO.IsNull() && myIO->hasEntry() && !myDlg->objectText( 0 ).isEmpty() ) &&
334       ( !myDlg->myGroupBox->isChecked() || !myDlg->myGroupListCmBox->currentText().isEmpty() ))
335   {
336     SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
337     if ( !mesh->_is_nil() )
338     {
339       if ( myDlg->getSelectionType() == SEL_OBJECT )
340         ok = true;
341       else
342       {
343         QString        ids = myDlg->objectText( 0 );
344         QStringList idList = ids.split( " ", QString::SkipEmptyParts );
345         const bool  isElem = ( myDlg->getSelectionType() == SEL_ELEMENTS );
346         QStringList::iterator idIt = idList.begin();
347         for ( ; idIt != idList.end() && !ok; ++idIt )
348           ok = ( mesh->GetElementType( idIt->toLong(), isElem ) != SMESH::ALL );
349       }
350     }
351   }
352
353   myDlg->button( QtxDialog::Apply )->setEnabled( ok );
354   myDlg->button( QtxDialog::OK    )->setEnabled( ok );
355 }
356
357 //================================================================================
358 /*!
359  * \brief Return a filter of objects
360  */
361 //================================================================================
362
363 SUIT_SelectionFilter* SMESHGUI_Add0DElemsOnAllNodesOp::createFilter( const int ) const
364 {
365   if ( myDlg->getSelectionType() == SEL_OBJECT )
366   {
367     // Create a filter of objects: any IDSource except the group of 0D elements
368
369     QList<SUIT_SelectionFilter*> filters;
370     filters.push_back( new SMESH_TypeFilter( SMESH::GROUP_0D ));
371     SMESH_LogicalFilter* not0DGroup = new SMESH_LogicalFilter( filters,
372                                                                SMESH_LogicalFilter::LO_NOT,
373                                                                /*takeOwnership=*/true);
374     filters[0] = not0DGroup;
375     filters.push_back( new SMESH_TypeFilter( SMESH::IDSOURCE ));
376     return new SMESH_LogicalFilter( filters,
377                                     SMESH_LogicalFilter::LO_AND,
378                                     /*takeOwnership=*/true);
379   }
380   return 0;
381 }
382
383 //================================================================================
384 /*!
385  * \brief Makes its main job
386  */
387 //================================================================================
388
389 bool SMESHGUI_Add0DElemsOnAllNodesOp::onApply()
390 {
391   if ( !myDlg->isValid() )
392     return false;
393
394   // get a mesh
395   SMESH::IDSource_wrap meshObject;
396   SMESH::SMESH_Mesh_var      mesh;
397   if ( !myIO.IsNull() )
398   {
399     CORBA::Object_var obj = SMESH::IObjectToObject( myIO );
400     meshObject = SMESH::SMESH_IDSource::_narrow( obj );
401     if ( !meshObject->_is_nil() )
402     {
403       mesh = meshObject->GetMesh();
404       meshObject->Register();
405     }
406   }
407   if ( mesh->_is_nil() )
408   {
409     SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), tr( "SMESH_BAD_SELECTION" ) );
410     return false;
411   }
412
413   try {
414     SMESH::SMESH_MeshEditor_var editor = mesh->GetMeshEditor();
415
416     // make SMESH_IDSource holding IDs of selected elements
417     if ( myDlg->getSelectionType() != SEL_OBJECT )
418     {
419       QString elemIDs = myDlg->objectText( 0 );
420       QStringList idList = elemIDs.split( " ", QString::SkipEmptyParts );
421       if ( idList.count() == 0 )
422       {
423         SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), tr( "SMESH_BAD_SELECTION" ) );
424         return false;
425       }
426       SMESH::long_array_var idArray = new SMESH::long_array;
427       idArray->length( idList.count() );
428       QStringList::iterator idIt = idList.begin();
429       for ( int i = 0; idIt != idList.end(); ++idIt, ++i )
430         idArray[i] = idIt->toLong();
431       SMESH::ElementType elemType =
432         myDlg->getSelectionType() == SEL_NODES ? SMESH::NODE : SMESH::ALL;
433       meshObject = editor->MakeIDSource( idArray, elemType );
434     }
435
436     // Create 0D elements
437
438     int prevNb0D = mesh->Nb0DElements();
439
440     QString groupName = myDlg->myGroupListCmBox->currentText();
441     SMESH::SMESH_IDSource_var newObj =
442       editor->Create0DElementsOnAllNodes( meshObject, groupName.toLatin1().data() );
443
444     int newNb0D = mesh->Nb0DElements() - prevNb0D;
445     SUIT_MessageBox::information( myDlg, tr( "SMESH_INFORMATION" ),
446                                   tr( "NB_NEW_0D" ).arg( newNb0D ),
447                                   SUIT_MessageBox::Ok, SUIT_MessageBox::Ok);
448   }
449   catch ( const SALOME::SALOME_Exception& S_ex ) {
450     SalomeApp_Tools::QtCatchCorbaException( S_ex );
451     return false;
452   }
453   catch (...) {
454     return false;
455   }
456
457   // clear selection
458
459   if ( myDlg->getSelectionType() == SEL_OBJECT )
460   {
461     SALOME_ListIO aList;
462     selectionMgr()->setSelectedObjects( aList, /*append=*/false );
463   }
464   else
465   {
466     selector()->ClearIndex();
467   }
468   selectionDone();
469
470   SMESH::UpdateView();
471   SMESHGUI::Modified();
472
473   if ( myDlg->myGroupBox->isChecked() )
474     SMESHGUI::GetSMESHGUI()->updateObjBrowser();
475
476   return true;
477 }
478
479 //================================================================================
480 /*!
481  * \brief Sets selection mode
482  */
483 //================================================================================
484
485 void SMESHGUI_Add0DElemsOnAllNodesOp::onSelTypeChange(int selType)
486 {
487   switch ( selType ) {
488   case SEL_OBJECT:   setSelectionMode( ActorSelection ); break;
489   case SEL_ELEMENTS: setSelectionMode( CellSelection );  break;
490   case SEL_NODES:    setSelectionMode( NodeSelection );  break;
491   }
492
493   if ( selType != SEL_OBJECT )
494     connect( myDlg, SIGNAL( objectChanged( int, const QStringList& )),
495              this,  SLOT  ( onTextChanged( int, const QStringList& )));
496   else
497     disconnect( myDlg, SIGNAL( objectChanged( int, const QStringList& )),
498                 this,  SLOT  ( onTextChanged( int, const QStringList& )));
499
500   selectionDone();
501 }
502
503 //================================================================================
504 /*!
505  * \brief Install filters
506  */
507 //================================================================================
508
509 void SMESHGUI_Add0DElemsOnAllNodesOp::onSetFilter()
510 {
511   SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
512   if ( mesh->_is_nil()) {
513     SUIT_MessageBox::critical( myDlg, tr("SMESH_ERROR"), tr("NO_MESH_SELECTED"));
514     return;
515   }
516   QList<int> types;
517   if ( myDlg->getSelectionType() == SEL_NODES ) {
518     types.push_back( SMESH::NODE );
519   }
520   else if ( myDlg->getSelectionType() == SEL_ELEMENTS ) {
521     types.push_back( SMESH::EDGE );
522     types.push_back( SMESH::FACE );
523     types.push_back( SMESH::VOLUME );
524   }
525   else
526     return;
527   if ( !myFilterDlg )
528     myFilterDlg = new SMESHGUI_FilterDlg( getSMESHGUI(), SMESH::ALL );
529
530   myFilterDlg->Init( types );
531   myFilterDlg->SetSelection();
532   myFilterDlg->SetMesh( mesh );
533   myFilterDlg->SetSourceWg( myDlg->objectWg( 0, LightApp_Dialog::Control ));
534
535   myFilterDlg->show();
536 }
537
538 //=======================================================================
539 //function : onTextChanged
540 //purpose  : SLOT called when the user types IDs
541 //=======================================================================
542
543 void SMESHGUI_Add0DElemsOnAllNodesOp::onTextChanged( int obj, const QStringList& text )
544 {
545   SMESHGUI_SelectionOp::onTextChanged( obj, text );
546   updateButtons();
547 }