Salome HOME
Merge remote branch 'origin/V8_5_asterstudy'
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_Add0DElemsOnAllNodesDlg.cxx
1 // Copyright (C) 2007-2016  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   myDuplicateElemsChkBox = new QCheckBox( tr( "SMESH_DUPLICATE_0D" ), mainFrame() );
108
109   // List of groups
110
111   myGroupBox = new QGroupBox( tr( "SMESH_ADD_TO_GROUP" ), mainFrame() );
112   myGroupBox->setCheckable( true );
113
114   myGroupLabel = new QLabel( tr( "SMESH_GROUP" ), myGroupBox );
115   myGroupListCmBox = new QComboBox( myGroupBox );
116   myGroupListCmBox->setEditable( true );
117   myGroupListCmBox->setInsertPolicy( QComboBox::NoInsert );
118
119   QHBoxLayout* groupsLayout = new QHBoxLayout( myGroupBox );
120   groupsLayout->setSpacing(SPACING);
121   groupsLayout->setMargin(MARGIN);
122   groupsLayout->addWidget( myGroupLabel );
123   groupsLayout->addWidget( myGroupListCmBox, 1 );
124
125   // Main layout
126
127   QGridLayout* aLay = new QGridLayout( mainFrame() );
128   aLay->setMargin(MARGIN);
129   aLay->setSpacing(SPACING);
130   //
131   aLay->addWidget( selTypeGrBox,          0, 0, 1, 5  );
132   //
133   aLay->addWidget( objectWg( 0, Label  ), 1, 0 );
134   aLay->addWidget( objectWg( 0, Btn    ), 1, 1 );
135   aLay->addWidget( objectWg( 0, Control), 1, 2, 1, 2 );
136   aLay->addWidget( myFilterBtn,           1, 4 );
137   aLay->addWidget( myDuplicateElemsChkBox,2, 0 );
138   //
139   aLay->addWidget( myGroupBox,            3, 0, 1, 5 );
140
141   // Signals
142
143   connect( myGroupBox,      SIGNAL( toggled( bool )),     SLOT( onGroupChecked() ));
144   connect( mySelTypeBtnGrp, SIGNAL( buttonClicked(int) ), SLOT( onSelTypeChange(int)));
145
146   onSelTypeChange( SEL_OBJECT );
147 }
148
149 //================================================================================
150 /*!
151  * \brief SLOT to enable/disable groups
152  */
153 //================================================================================
154
155 void SMESHGUI_Add0DElemsOnAllNodesDlg::onGroupChecked( bool on )
156 {
157   myGroupLabel->setEnabled( on );
158   myGroupListCmBox->setEnabled( on );
159 }
160
161 //================================================================================
162 /*!
163  * \brief SLOT to enable/disable groups
164  */
165 //================================================================================
166
167 void SMESHGUI_Add0DElemsOnAllNodesDlg::onSelTypeChange( int selType )
168 {
169   setNameIndication( 0, selType == SEL_OBJECT ? OneName : ListOfNames );
170   setReadOnly      ( 0, selType == SEL_OBJECT );
171
172   QLabel* label = qobject_cast< QLabel* >( objectWg(0, Label ));
173   switch( selType ) {
174   case SEL_OBJECT:   label->setText( tr("SMESH_NAME")); break;
175   case SEL_ELEMENTS: label->setText( tr("ELEMENT_IDS")); break;
176   case SEL_NODES:    label->setText( tr("NODE_IDS")); break;
177   default:;
178   }
179   QLineEdit* lineEdit = qobject_cast< QLineEdit* >( objectWg(0, Control ));
180   lineEdit->setText("");
181   lineEdit->setValidator( selType == SEL_OBJECT ? 0 : & myIDValidator );
182
183   myFilterBtn->setEnabled( selType != SEL_OBJECT );
184
185   emit selTypeChanged( selType );
186 }
187
188 //================================================================================
189 /*!
190  * \brief Return type of selected object: [SEL_OBJECT, SEL_ELEMENTS, SEL_NODES]
191  */
192 //================================================================================
193
194 int SMESHGUI_Add0DElemsOnAllNodesDlg::getSelectionType() const
195 {
196   return mySelTypeBtnGrp->checkedId();
197 }
198
199 //================================================================================
200 /*!
201  * \brief Checks consistency of data
202  */
203 //================================================================================
204
205 bool SMESHGUI_Add0DElemsOnAllNodesDlg::isValid()
206 {
207   if( myGroupBox->isChecked() && myGroupListCmBox->currentText().isEmpty() ) {
208     SUIT_MessageBox::warning( this, tr( "SMESH_WRN_WARNING" ), tr( "GROUP_NAME_IS_EMPTY" ) );
209     return false;
210   }
211   return true;
212 }
213
214 //================================================================================
215 /*!
216  * \brief Operation Constructor
217  */
218 //================================================================================
219
220 SMESHGUI_Add0DElemsOnAllNodesOp::SMESHGUI_Add0DElemsOnAllNodesOp()
221   :SMESHGUI_SelectionOp(),
222    myDlg( new SMESHGUI_Add0DElemsOnAllNodesDlg ),
223    myFilterDlg( 0 )
224 {
225   myHelpFileName = "adding_nodes_and_elements.html#adding-0delems-on-all-nodes-anchor";
226
227   connect( myDlg,              SIGNAL( selTypeChanged(int) ), SLOT( onSelTypeChange(int)));
228   connect( myDlg->myFilterBtn, SIGNAL( clicked()),            SLOT( onSetFilter() ));
229   connect( myDlg->myGroupBox,  SIGNAL( clicked(bool)),        SLOT( updateButtons() ));
230 }
231
232 //================================================================================
233 /*!
234  * \brief Destructor
235  */
236 //================================================================================
237
238 SMESHGUI_Add0DElemsOnAllNodesOp::~SMESHGUI_Add0DElemsOnAllNodesOp()
239 {
240   if ( myFilterDlg ) {
241     myFilterDlg->setParent( 0 );
242     delete myFilterDlg;
243     myFilterDlg = 0;
244   }
245 }
246
247 //================================================================================
248 /*!
249  * \brief Start
250  */
251 //================================================================================
252
253 void SMESHGUI_Add0DElemsOnAllNodesOp::startOperation()
254 {
255   SMESHGUI_SelectionOp::startOperation();
256
257   myDlg->myGroupBox->setChecked( false );
258   myDlg->activateObject( 0 );
259   myDlg->show();
260
261   selectionDone();
262 }
263
264 //================================================================================
265 /*!
266  * \brief Treat changed selection
267  */
268 //================================================================================
269
270 void SMESHGUI_Add0DElemsOnAllNodesOp::selectionDone()
271 {
272   if (myFilterDlg && myFilterDlg->isVisible()) return; // filter dgl active
273   if (!myDlg->myGroupBox->isEnabled())         return; // inactive
274
275   myIO.Nullify();
276   updateButtons();
277
278   SALOME_ListIO aList;
279   selectionMgr()->selectedObjects( aList );
280   if ( aList.Extent() == 1 ) {
281     myIO = aList.First();
282   }
283   else {
284     myDlg->setObjectText( 0, ""); // it clears the selection
285     return;
286   }
287   QString ids;
288   switch ( myDlg->getSelectionType() ) {
289   case SEL_OBJECT:
290     SMESHGUI_SelectionOp::selectionDone();
291     break;
292   case SEL_ELEMENTS:
293     SMESH::GetNameOfSelectedElements( selector(), myIO, ids );
294     myDlg->setObjectText( 0, ids );
295     break;
296   case SEL_NODES:
297     SMESH::GetNameOfSelectedNodes( selector(), myIO, ids );
298     myDlg->setObjectText( 0, ids );
299     break;
300   default:;
301   }
302
303   // fill the list of existing groups
304   myDlg->myGroupListCmBox->clear();
305   myDlg->myGroupListCmBox->addItem( QString() );
306   if ( !myIO.IsNull() && myIO->hasEntry())
307   {
308     SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
309     _PTR(SObject)       meshSO = SMESH::ObjectToSObject( mesh );
310     _PTR(SObject) group0DRoot;
311     if ( meshSO && meshSO->FindSubObject( SMESH::Tag_0DElementsGroups, group0DRoot ))
312     {
313       _PTR(ChildIterator) group0DIter = SMESH::getStudy()->NewChildIterator( group0DRoot );
314       for ( ; group0DIter->More(); group0DIter->Next() )
315       {
316         _PTR(SObject) groupSO = group0DIter->Value();
317         std::string groupName = groupSO->GetName();
318         if ( !groupName.empty() )
319           myDlg->myGroupListCmBox->addItem( groupName.c_str() );
320       }
321     }
322     // enable buttons
323     updateButtons();
324   }
325 }
326
327 //=======================================================================
328 //function : updateButtons
329 //purpose  : enable [Apply]
330 //=======================================================================
331
332 void SMESHGUI_Add0DElemsOnAllNodesOp::updateButtons()
333 {
334   bool ok = false;
335
336   if (( !myIO.IsNull() && myIO->hasEntry() && !myDlg->objectText( 0 ).isEmpty() ) &&
337       ( !myDlg->myGroupBox->isChecked() || !myDlg->myGroupListCmBox->currentText().isEmpty() ))
338   {
339     SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
340     if ( !mesh->_is_nil() )
341     {
342       if ( myDlg->getSelectionType() == SEL_OBJECT )
343         ok = true;
344       else
345       {
346         QString        ids = myDlg->objectText( 0 );
347         QStringList idList = ids.split( " ", QString::SkipEmptyParts );
348         const bool  isElem = ( myDlg->getSelectionType() == SEL_ELEMENTS );
349         QStringList::iterator idIt = idList.begin();
350         for ( ; idIt != idList.end() && !ok; ++idIt )
351           ok = ( mesh->GetElementType( idIt->toLong(), isElem ) != SMESH::ALL );
352       }
353     }
354   }
355
356   myDlg->button( QtxDialog::Apply )->setEnabled( ok );
357   myDlg->button( QtxDialog::OK    )->setEnabled( ok );
358 }
359
360 //================================================================================
361 /*!
362  * \brief Return a filter of objects
363  */
364 //================================================================================
365
366 SUIT_SelectionFilter* SMESHGUI_Add0DElemsOnAllNodesOp::createFilter( const int ) const
367 {
368   if ( myDlg->getSelectionType() == SEL_OBJECT )
369   {
370     // Create a filter of objects: any IDSource except the group of 0D elements
371
372     QList<SUIT_SelectionFilter*> filters;
373     filters.push_back( new SMESH_TypeFilter( SMESH::GROUP_0D ));
374     SMESH_LogicalFilter* not0DGroup = new SMESH_LogicalFilter( filters,
375                                                                SMESH_LogicalFilter::LO_NOT,
376                                                                /*takeOwnership=*/true);
377     filters[0] = not0DGroup;
378     filters.push_back( new SMESH_TypeFilter( SMESH::IDSOURCE ));
379     return new SMESH_LogicalFilter( filters,
380                                     SMESH_LogicalFilter::LO_AND,
381                                     /*takeOwnership=*/true);
382   }
383   return 0;
384 }
385
386 //================================================================================
387 /*!
388  * \brief Makes its main job
389  */
390 //================================================================================
391
392 bool SMESHGUI_Add0DElemsOnAllNodesOp::onApply()
393 {
394   if ( !myDlg->isValid() )
395     return false;
396
397   // get a mesh
398   SMESH::IDSource_wrap meshObject;
399   SMESH::SMESH_Mesh_var      mesh;
400   if ( !myIO.IsNull() )
401   {
402     CORBA::Object_var obj = SMESH::IObjectToObject( myIO );
403     meshObject = SMESH::SMESH_IDSource::_narrow( obj );
404     if ( !meshObject->_is_nil() )
405     {
406       mesh = meshObject->GetMesh();
407       meshObject->Register();
408     }
409   }
410   if ( mesh->_is_nil() )
411   {
412     SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), tr( "SMESH_BAD_SELECTION" ) );
413     return false;
414   }
415
416   try {
417     SMESH::SMESH_MeshEditor_var editor = mesh->GetMeshEditor();
418
419     // make SMESH_IDSource holding IDs of selected elements
420     if ( myDlg->getSelectionType() != SEL_OBJECT )
421     {
422       QString elemIDs = myDlg->objectText( 0 );
423       QStringList idList = elemIDs.split( " ", QString::SkipEmptyParts );
424       if ( idList.count() == 0 )
425       {
426         SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), tr( "SMESH_BAD_SELECTION" ) );
427         return false;
428       }
429       SMESH::long_array_var idArray = new SMESH::long_array;
430       idArray->length( idList.count() );
431       QStringList::iterator idIt = idList.begin();
432       for ( int i = 0; idIt != idList.end(); ++idIt, ++i )
433         idArray[i] = idIt->toLong();
434       SMESH::ElementType elemType =
435         myDlg->getSelectionType() == SEL_NODES ? SMESH::NODE : SMESH::ALL;
436       meshObject = editor->MakeIDSource( idArray, elemType );
437     }
438
439     // Create 0D elements
440
441     int prevNb0D = mesh->Nb0DElements();
442
443     QString groupName = myDlg->myGroupListCmBox->currentText();
444     SMESH::SMESH_IDSource_var newObj =
445       editor->Create0DElementsOnAllNodes( meshObject, groupName.toUtf8().data(),
446                                           myDlg->myDuplicateElemsChkBox->isChecked() );
447
448     int newNb0D = mesh->Nb0DElements() - prevNb0D;
449     SUIT_MessageBox::information( myDlg, tr( "SMESH_INFORMATION" ),
450                                   tr( "NB_NEW_0D" ).arg( newNb0D ),
451                                   SUIT_MessageBox::Ok, SUIT_MessageBox::Ok);
452   }
453   catch ( const SALOME::SALOME_Exception& S_ex ) {
454     SalomeApp_Tools::QtCatchCorbaException( S_ex );
455     return false;
456   }
457   catch (...) {
458     return false;
459   }
460
461   // clear selection
462
463   if ( myDlg->getSelectionType() == SEL_OBJECT )
464   {
465     SALOME_ListIO aList;
466     selectionMgr()->setSelectedObjects( aList, /*append=*/false );
467   }
468   else
469   {
470     selector()->ClearIndex();
471   }
472   selectionDone();
473
474   SMESH::UpdateView();
475   SMESHGUI::Modified();
476
477   if ( myDlg->myGroupBox->isChecked() )
478     SMESHGUI::GetSMESHGUI()->updateObjBrowser();
479
480   return true;
481 }
482
483 //================================================================================
484 /*!
485  * \brief Sets selection mode
486  */
487 //================================================================================
488
489 void SMESHGUI_Add0DElemsOnAllNodesOp::onSelTypeChange(int selType)
490 {
491   switch ( selType ) {
492   case SEL_OBJECT:   setSelectionMode( ActorSelection ); break;
493   case SEL_ELEMENTS: setSelectionMode( CellSelection );  break;
494   case SEL_NODES:    setSelectionMode( NodeSelection );  break;
495   }
496
497   if ( selType != SEL_OBJECT )
498     connect( myDlg, SIGNAL( objectChanged( int, const QStringList& )),
499              this,  SLOT  ( onTextChanged( int, const QStringList& )));
500   else
501     disconnect( myDlg, SIGNAL( objectChanged( int, const QStringList& )),
502                 this,  SLOT  ( onTextChanged( int, const QStringList& )));
503
504   connect( myDlg->myGroupListCmBox, SIGNAL( editTextChanged(const QString & )),
505            this,                    SLOT(   updateButtons() ));
506
507   selectionDone();
508 }
509
510 //================================================================================
511 /*!
512  * \brief Install filters
513  */
514 //================================================================================
515
516 void SMESHGUI_Add0DElemsOnAllNodesOp::onSetFilter()
517 {
518   SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
519   if ( mesh->_is_nil()) {
520     SUIT_MessageBox::critical( myDlg, tr("SMESH_ERROR"), tr("NO_MESH_SELECTED"));
521     return;
522   }
523   QList<int> types;
524   if ( myDlg->getSelectionType() == SEL_NODES ) {
525     types.push_back( SMESH::NODE );
526   }
527   else if ( myDlg->getSelectionType() == SEL_ELEMENTS ) {
528     types.push_back( SMESH::EDGE );
529     types.push_back( SMESH::FACE );
530     types.push_back( SMESH::VOLUME );
531   }
532   else
533     return;
534   if ( !myFilterDlg )
535     myFilterDlg = new SMESHGUI_FilterDlg( getSMESHGUI(), SMESH::ALL );
536
537   myFilterDlg->Init( types );
538   myFilterDlg->SetSelection();
539   myFilterDlg->SetMesh( mesh );
540   myFilterDlg->SetSourceWg( myDlg->objectWg( 0, LightApp_Dialog::Control ));
541
542   myFilterDlg->show();
543 }
544
545 //=======================================================================
546 //function : onTextChanged
547 //purpose  : SLOT called when the user types IDs
548 //=======================================================================
549
550 void SMESHGUI_Add0DElemsOnAllNodesOp::onTextChanged( int obj, const QStringList& text )
551 {
552   SMESHGUI_SelectionOp::onTextChanged( obj, text );
553   updateButtons();
554 }