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