Salome HOME
Update of CheckDone
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_DuplicateNodesDlg.cxx
1 // Copyright (C) 2007-2020  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_DuplicateNodesDlg.cxx
25 // Author : Michael ZORIN, Open CASCADE S.A.S.
26
27 // SMESH includes
28 #include "SMESHGUI_DuplicateNodesDlg.h"
29
30 #include "SMESHGUI.h"
31 #include "SMESHGUI_Utils.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_VTKUtils.h"
34
35 #include <SMESH_TypeFilter.hxx>
36
37 // SALOME GUI includes
38 #include <SUIT_Session.h>
39 #include <SUIT_ResourceMgr.h>
40 #include <SUIT_Desktop.h>
41 #include <SUIT_MessageBox.h>
42 #include <SUIT_OverrideCursor.h>
43
44 #include <LightApp_Application.h>
45 #include <LightApp_SelectionMgr.h>
46
47 #include <SalomeApp_Tools.h>
48
49 #include <SVTK_ViewWindow.h>
50 #include <SALOME_ListIO.hxx>
51
52 // Qt includes
53 #include <QApplication>
54 #include <QButtonGroup>
55 #include <QGroupBox>
56 #include <QLabel>
57 #include <QLineEdit>
58 #include <QPushButton>
59 #include <QRadioButton>
60 #include <QCheckBox>
61 #include <QHBoxLayout>
62 #include <QVBoxLayout>
63 #include <QKeyEvent>
64
65 #include <utilities.h>
66 #include <SALOMEDSClient_SObject.hxx>
67
68 // IDL includes
69 #include <SALOMEconfig.h>
70 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
71
72 #define SPACING 6
73 #define MARGIN  11
74
75 /*!
76   \class BusyLocker
77   \brief Simple 'busy state' flag locker.
78   \internal
79 */
80
81 class BusyLocker
82 {
83 public:
84   //! Constructor. Sets passed boolean flag to \c true.
85   BusyLocker( bool& busy ) : myBusy( busy ) { myBusy = true; }
86   //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
87   ~BusyLocker() { myBusy = false; }
88 private:
89   bool& myBusy; //! External 'busy state' boolean flag
90 };
91
92 /*!
93   \brief Constructor
94   \param theModule Mesh module instance
95 */
96 SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
97   : QDialog( SMESH::GetDesktop( theModule ) ),
98     mySMESHGUI( theModule ),
99     mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
100 {
101   // Dialog attributes
102   setModal(false);
103   setAttribute(Qt::WA_DeleteOnClose, true);
104   setWindowTitle(tr("SMESH_DUPLICATE_TITLE"));
105   setSizeGripEnabled(true);
106
107   // Icons for the dialog operation modes and selection button
108   SUIT_ResourceMgr* aResMgr = SMESH::GetResourceMgr( mySMESHGUI );
109   QPixmap iconWithoutElem (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_NODES")));
110   QPixmap iconWithElem (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_NODES_WITH_ELEM")));
111   QPixmap iconElemOnly (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_ELEM_ONLY")));
112   QPixmap iconGrpBoundary (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_DUPLICATE_GROUP_BOUNDARY")));
113   QPixmap iconSelect (aResMgr->loadPixmap("SMESH", tr("ICON_SELECT")));
114
115   // Main layout
116   QVBoxLayout* aMainLayout = new QVBoxLayout(this);
117   aMainLayout->setSpacing(SPACING);
118   aMainLayout->setMargin(MARGIN);
119
120   // Operation modes selector
121   QGroupBox* aConstructorsBox = new QGroupBox(tr("DUPLICATION_MODE"), this);
122   myGroupConstructors = new QButtonGroup(this);
123   QHBoxLayout* aConstructorsBoxLayout = new QHBoxLayout(aConstructorsBox);
124   aConstructorsBoxLayout->setSpacing(SPACING);
125   aConstructorsBoxLayout->setMargin(MARGIN);
126
127   QRadioButton* aRadioButton1 = new QRadioButton(aConstructorsBox);
128   aRadioButton1->setIcon(iconWithoutElem);
129   QRadioButton* aRadioButton2 = new QRadioButton(aConstructorsBox);
130   aRadioButton2->setIcon(iconWithElem);
131   QRadioButton* aRadioButton3 = new QRadioButton(aConstructorsBox);
132   aRadioButton3->setIcon(iconElemOnly);
133   QRadioButton* aRadioButton4 = new QRadioButton(aConstructorsBox);
134   aRadioButton4->setIcon(iconGrpBoundary);
135   
136   aConstructorsBoxLayout->addWidget(aRadioButton1);
137   aConstructorsBoxLayout->addWidget(aRadioButton2);
138   aConstructorsBoxLayout->addWidget(aRadioButton3);
139   aConstructorsBoxLayout->addWidget(aRadioButton4);
140   myGroupConstructors->addButton(aRadioButton1, 0);
141   myGroupConstructors->addButton(aRadioButton2, 1);
142   myGroupConstructors->addButton(aRadioButton3, 2);
143   myGroupConstructors->addButton(aRadioButton4, 3);
144
145   // Arguments
146   myGroupArguments = new QGroupBox(this);
147   QGridLayout* aGroupArgumentsLayout = new QGridLayout(myGroupArguments);
148   aGroupArgumentsLayout->setSpacing(SPACING);
149   aGroupArgumentsLayout->setMargin(MARGIN);
150     
151   myTextLabel1 = new QLabel(myGroupArguments);
152   mySelectButton1 = new QPushButton(myGroupArguments);
153   mySelectButton1->setIcon(iconSelect);
154   myLineEdit1 = new QLineEdit(myGroupArguments);
155   myLineEdit1->setReadOnly(true);
156
157   myTextLabel2 = new QLabel(myGroupArguments);
158   mySelectButton2 = new QPushButton(myGroupArguments);
159   mySelectButton2->setIcon(iconSelect);
160   myLineEdit2 = new QLineEdit(myGroupArguments);
161   myLineEdit2->setReadOnly(true);
162
163   myTextLabel3 = new QLabel(myGroupArguments);
164   mySelectButton3 = new QPushButton(myGroupArguments);
165   mySelectButton3->setIcon(iconSelect);
166   myLineEdit3 = new QLineEdit(myGroupArguments);
167   myLineEdit3->setReadOnly(true);
168   myGenerateButton3 = new QPushButton(tr("GENERATE_GROUPS"), myGroupArguments);
169
170   myCheckBox1 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_ELEMENTS"), myGroupArguments);
171   myCheckBox2 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_NODES"), myGroupArguments);
172
173   aGroupArgumentsLayout->addWidget(myTextLabel1,     0, 0);
174   aGroupArgumentsLayout->addWidget(mySelectButton1,  0, 1);
175   aGroupArgumentsLayout->addWidget(myLineEdit1,      0, 2, 1, 2);
176   aGroupArgumentsLayout->addWidget(myTextLabel2,     1, 0);
177   aGroupArgumentsLayout->addWidget(mySelectButton2,  1, 1);
178   aGroupArgumentsLayout->addWidget(myLineEdit2,      1, 2, 1, 2);
179   aGroupArgumentsLayout->addWidget(myTextLabel3,     2, 0);
180   aGroupArgumentsLayout->addWidget(mySelectButton3,  2, 1);
181   aGroupArgumentsLayout->addWidget(myLineEdit3,      2, 2);
182   aGroupArgumentsLayout->addWidget(myGenerateButton3,2, 3);
183   aGroupArgumentsLayout->addWidget(myCheckBox1,      3, 0);
184   aGroupArgumentsLayout->addWidget(myCheckBox2,      4, 0);
185   aGroupArgumentsLayout->setRowStretch(5, 1);
186   
187   // Buttons
188   QGroupBox* aGroupButtons = new QGroupBox(this);
189   QHBoxLayout* aGroupButtonsLayout = new QHBoxLayout(aGroupButtons);
190   aGroupButtonsLayout->setSpacing(SPACING);
191   aGroupButtonsLayout->setMargin(MARGIN);
192
193   myButtonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), aGroupButtons);
194   myButtonOk->setAutoDefault(true);
195   myButtonOk->setDefault(true);
196   myButtonApply = new QPushButton(tr("SMESH_BUT_APPLY"), aGroupButtons);
197   myButtonApply->setAutoDefault(true);
198   myButtonClose = new QPushButton(tr("SMESH_BUT_CLOSE"), aGroupButtons);
199   myButtonClose->setAutoDefault(true);
200   myButtonHelp = new QPushButton(tr("SMESH_BUT_HELP"), aGroupButtons);
201   myButtonHelp->setAutoDefault(true);
202
203   aGroupButtonsLayout->addWidget(myButtonOk);
204   aGroupButtonsLayout->addSpacing(10);
205   aGroupButtonsLayout->addWidget(myButtonApply);
206   aGroupButtonsLayout->addSpacing(10);
207   aGroupButtonsLayout->addStretch();
208   aGroupButtonsLayout->addWidget(myButtonClose);
209   aGroupButtonsLayout->addWidget(myButtonHelp);
210
211   // Add mode selector, arguments and buttons to the main layout
212   aMainLayout->addWidget(aConstructorsBox);
213   aMainLayout->addWidget(myGroupArguments);
214   aMainLayout->addWidget(aGroupButtons);
215   
216   myCheckBox1->setChecked(true);
217   myCheckBox2->setChecked(true);
218
219   // Initialize the dialog
220   Init();
221
222   // Help file name
223   myHelpFileName = "double_nodes_page.html";
224
225   // Signals and slots connections
226   connect(myGroupConstructors, SIGNAL(buttonClicked(int)), SLOT(onConstructorsClicked(int)));
227      
228   connect(mySelectButton1, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
229   connect(mySelectButton2, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
230   connect(mySelectButton3, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
231   connect(myGenerateButton3, SIGNAL (clicked()), this, SLOT(onGenerate()));
232
233   connect(myCheckBox2,    SIGNAL(stateChanged(int)), SLOT(updateButtons()));
234
235   connect(myButtonOk,     SIGNAL(clicked()), this, SLOT(onOk()));
236   connect(myButtonClose,  SIGNAL(clicked()), this, SLOT(reject()));
237   connect(myButtonApply,  SIGNAL(clicked()), this, SLOT(onApply()));
238   connect(myButtonHelp,   SIGNAL(clicked()), this, SLOT(onHelp()));
239   
240   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionChanged()));
241
242   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(onDeactivate()));
243   connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
244 }
245
246 /*!
247   \brief Destructor
248 */
249 SMESHGUI_DuplicateNodesDlg::~SMESHGUI_DuplicateNodesDlg()
250 {
251 }
252
253 /*!
254   \brief Destructor
255 */
256 void SMESHGUI_DuplicateNodesDlg::Init()
257 {
258   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
259
260   // Set initial parameters
261   myBusy = false;
262   myCurrentLineEdit = myLineEdit1;
263
264   myGroups1.clear();
265   myGroups2.clear();
266   myGroups3.clear();
267   
268   // Set selection mode
269   mySelectionMgr->installFilter(new SMESH_TypeFilter(SMESH::GROUP));
270   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
271     aViewWindow->SetSelectionMode(ActorSelection);
272   
273   // Set construction mode
274   int operationMode = myGroupConstructors->checkedId();
275   if (operationMode < 0) {
276     // The dialog has been just displayed
277     operationMode = 0;
278     myGroupConstructors->button(0)->setChecked(true);
279   }
280   onConstructorsClicked(operationMode);
281 }
282
283 /*!
284   \brief SLOT called to change the dialog operation mode.
285   \param constructorId id of the radio button in mode selector button group
286 */
287 void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
288 {
289   // Clear all fields
290   myLineEdit1->clear();
291   myLineEdit2->clear();
292   myLineEdit3->clear();
293
294   myGroups1.clear();
295   myGroups2.clear();
296   myGroups3.clear();
297
298   // Set the first field as current
299   myCurrentLineEdit = myLineEdit1;
300   myCurrentLineEdit->setFocus();
301
302   switch (constructorId) {
303   case 0:
304     {
305       // Set text to the group of arguments and to the first two labels
306       myGroupArguments->setTitle(tr("DUPLICATION_WITHOUT_ELEMS"));
307       myTextLabel1->setText(tr("GROUP_NODES_TO_DUPLICATE"));
308       myTextLabel3->setText(tr("GROUP_NODES_TO_REPLACE"));
309
310       myCheckBox1->hide();
311       myCheckBox2->show();
312       myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
313       
314       // Hide the 2nd field
315       myTextLabel2     ->hide();
316       mySelectButton2  ->hide();
317       myLineEdit2      ->hide();
318       myTextLabel3     ->show();
319       mySelectButton3  ->show();
320       myLineEdit3      ->show();
321       myGenerateButton3->show();
322
323       break;
324     }
325   case 1:
326     {
327       // Set text to the group of arguments and to all the labels
328       myGroupArguments->setTitle(tr("DUPLICATION_WITH_ELEMS"));
329       myTextLabel1->setText(tr("GROUP_ELEMS_TO_DUPLICATE"));
330       myTextLabel2->setText(tr("GROUP_NODES_NOT_DUPLICATE"));
331       myTextLabel3->setText(tr("GROUP_ELEMS_TO_REPLACE"));
332       
333       myCheckBox1->show();
334       myCheckBox2->show();
335       myCheckBox1->setText( tr("CONSTRUCT_NEW_GROUP_ELEMENTS"));
336       myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
337
338       // Show the 2nd field
339       myTextLabel2     ->show();
340       mySelectButton2  ->show();
341       myLineEdit2      ->show();
342       myTextLabel3     ->show();
343       mySelectButton3  ->show();
344       myLineEdit3      ->show();
345       myGenerateButton3->show();
346
347       break;
348     }
349   case 2:
350     {
351       // Set text to the group of arguments and to all the labels
352       myGroupArguments->setTitle(tr("DUPLICATION_ONLY_ELEMS"));
353       myTextLabel1->setText(tr("GROUP_ELEMS_TO_DUPLICATE"));
354       
355       myCheckBox1->show();
356       myCheckBox1->setText( tr("CONSTRUCT_NEW_GROUP_ELEMENTS"));
357       myCheckBox2->hide();
358
359       // Hide the second and the third field
360       myTextLabel2     ->hide();
361       mySelectButton2  ->hide();
362       myLineEdit2      ->hide();
363       myTextLabel3     ->hide();
364       mySelectButton3  ->hide();
365       myLineEdit3      ->hide();
366       myGenerateButton3->hide();
367
368       break;
369     }
370   case 3:
371     {
372       // Set text to the group of arguments and to all the labels
373       myGroupArguments->setTitle(tr("DUPLICATION_GROUP_BOUNDARY"));
374       myTextLabel1->setText(tr("GROUP_VOLUME_GROUPS"));
375       
376       myCheckBox1->show();
377       myCheckBox2->show();
378       myCheckBox1->setText( tr("CREATE_JOINT_ELEMENTS"));
379       myCheckBox2->setText( tr("ON_ALL_BOUNDARIES"));
380
381       // Hide the second and the third field
382       myTextLabel2     ->hide();
383       mySelectButton2  ->hide();
384       myLineEdit2      ->hide();
385       myTextLabel3     ->hide();
386       mySelectButton3  ->hide();
387       myLineEdit3      ->hide();
388       myGenerateButton3->hide();
389
390       break;
391     }
392   }
393   myGroupArguments->hide();
394   myGroupArguments->show();
395   this->resize(this->sizeHint().width(), this->minimumSizeHint().height());
396   // Process selection
397   onSelectionChanged();
398 }
399
400 /*!
401   \brief SLOT called to apply changes.
402 */
403 bool SMESHGUI_DuplicateNodesDlg::onApply()
404 {
405   if ( SMESHGUI::isStudyLocked() || !isValid() )
406     return false;
407
408   BusyLocker lock( myBusy );
409  
410   bool toCreateElemGroup = myCheckBox1->isChecked();
411   bool toCreateNodeGroup = myCheckBox2->isChecked();
412   int operationMode      = myGroupConstructors->checkedId();
413   
414   // Apply changes
415   bool result = false;
416   SUIT_OverrideCursor aWaitCursor;
417   QStringList anEntryList;
418
419   try {
420     SMESH::SMESH_Mesh_var             aMesh = myGroups1[0]->GetMesh();
421     SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
422
423     switch ( operationMode ) {
424     case 0:
425     {
426       SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
427       g1->length( myGroups1.count() );
428       for ( int i = 0; i < myGroups1.count(); i++ )
429         g1[i] = myGroups1[i];
430       SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups();
431       g2->length( myGroups3.count() );
432       for ( int i = 0; i < myGroups3.count(); i++ )
433         g2[i] = myGroups3[i];
434
435       if ( toCreateNodeGroup ) {
436         SMESH::SMESH_GroupBase_var aNewGroup = 
437           aMeshEditor->DoubleNodeGroupsNew( g1.in(), g2.in() );
438         result = !CORBA::is_nil( aNewGroup );
439       }
440       else {
441         result = aMeshEditor->DoubleNodeGroups( g1.in(), g2.in() );
442       }
443       break;
444     }
445     case 1:
446     {
447       SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
448       g1->length( myGroups1.count() );
449       for ( int i = 0; i < myGroups1.count(); i++ )
450         g1[i] = myGroups1[i];
451       SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups();
452       g2->length( myGroups2.count() );
453       for ( int i = 0; i < myGroups2.count(); i++ )
454         g2[i] = myGroups2[i];
455       SMESH::ListOfGroups_var g3 = new SMESH::ListOfGroups();
456       g3->length( myGroups3.count() );
457
458       for ( int i = 0; i < myGroups3.count(); i++ )
459         g3[i] = myGroups3[i];
460       if ( toCreateElemGroup || toCreateNodeGroup ) {
461         SMESH::ListOfGroups_var aNewGroups = 
462           aMeshEditor->DoubleNodeElemGroups2New( g1.in(), g2.in(), g3.in(),
463                                                  toCreateElemGroup, toCreateNodeGroup );
464         result = ( aNewGroups[ !toCreateElemGroup ].in() );
465       }
466       else {
467         result = aMeshEditor->DoubleNodeElemGroups( g1.in(), g2.in(), g3.in() );
468       }
469       break;
470     }
471     case 2:
472     {
473       result = true;
474       QString groupName;
475       if ( toCreateElemGroup )
476         groupName = SMESH::UniqueName("DoubleElements");
477       for ( int i = 0; i < myGroups1.count(); i++ )
478       {
479         SMESH::SMESH_Group_var group =
480           aMeshEditor->DoubleElements( myGroups1[i], groupName.toUtf8().data() );
481         if ( group->_is_nil() )
482         {
483           if ( toCreateElemGroup )
484             result = false;
485         }
486         else
487         {
488           if ( _PTR(SObject) so = SMESH::FindSObject( group ))
489             anEntryList.append( so->GetID().c_str() );
490         }
491       }
492       break;
493     }
494     case 3:
495     {
496       bool createJointElems = myCheckBox1->isChecked();
497       bool onAllBoundaries  = myCheckBox2->isChecked();
498
499       SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
500       g1->length( myGroups1.count() );
501       for ( int i = 0; i < myGroups1.count(); i++ )
502         g1[i] = myGroups1[i];
503
504       result = aMeshEditor->DoubleNodesOnGroupBoundaries( g1.in(), createJointElems, onAllBoundaries );
505
506       break;
507     }
508     } // switch( operationMode )
509   }
510   catch (const SALOME::SALOME_Exception& S_ex) {
511     SalomeApp_Tools::QtCatchCorbaException(S_ex);
512   }
513   catch ( const std::exception& exc ) {
514     INFOS( "Follow exception was caught:\n\t" << exc.what() );
515   }
516   catch (...) {
517     INFOS( "Unknown exception was caught !!!" );
518   }
519
520   if (!result) {
521     SUIT_MessageBox::warning(this,
522                              tr("SMESH_WRN_WARNING"),
523                              tr("SMESH_OPERATION_FAILED"));
524     return false;
525   }
526
527   // Update GUI
528   mySelectionMgr->clearSelected();
529   SMESH::UpdateView();
530   SMESHGUI::Modified();
531   mySMESHGUI->updateObjBrowser(true);
532
533   if ( !anEntryList.isEmpty())
534     if( LightApp_Application* anApp =
535         dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() ))
536       anApp->browseObjects( anEntryList, true, false );
537
538   // Reinitialize the dialog
539   Init();
540
541   return true;
542 }
543
544 /*!
545   \brief SLOT called to apply changes and close the dialog.
546 */
547 void SMESHGUI_DuplicateNodesDlg::onOk()
548 {
549   if (onApply())
550     reject();
551 }
552
553 /*!
554   \brief SLOT called to close the dialog.
555 */
556 void SMESHGUI_DuplicateNodesDlg::reject()
557 {
558   disconnect(mySelectionMgr, 0, this, 0);
559   disconnect(mySMESHGUI, 0, this, 0);
560   mySMESHGUI->ResetState();
561   mySelectionMgr->clearFilters();
562   QDialog::reject();
563 }
564
565 /*!
566   \brief  SLOT called when selection changed.
567 */
568 void SMESHGUI_DuplicateNodesDlg::onSelectionChanged()
569 {
570   if ( myBusy || !isEnabled() ) return;
571   
572   int operationMode = myGroupConstructors->checkedId();
573
574   SALOME_ListIO aList;
575   mySelectionMgr->selectedObjects( aList );
576   //int aNbSel = aList.Extent();
577
578   QList<SMESH::SMESH_GroupBase_var> aGroups;
579
580   SALOME_ListIteratorOfListIO anIter ( aList );
581   bool ok = true;
582   for ( ; anIter.More() && ok; anIter.Next()) {
583     SMESH::SMESH_GroupBase_var aGroup = SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>( anIter.Value() );
584     // check group is selected
585     ok = !CORBA::is_nil( aGroup );
586     // check groups of the same mesh are selected
587     if ( ok ) {
588       SMESH::SMESH_Mesh_var aMesh1;
589       if ( !aGroups.isEmpty() ) aMesh1 = aGroups[0]->GetMesh();
590       SMESH::SMESH_Mesh_var aMesh2 = aGroup->GetMesh();
591       ok = CORBA::is_nil( aMesh1 ) || aMesh1->_is_equivalent( aMesh2 );
592     }
593     // check group of proper type is selected
594     if ( ok ) {
595       SMESH::ElementType aGroupType = aGroup->GetType();
596       switch ( operationMode ) {
597       case 0:
598         ok = ( myCurrentLineEdit == myLineEdit1 && aGroupType == SMESH::NODE ) ||
599              ( myCurrentLineEdit == myLineEdit2 && aGroupType != SMESH::NODE );
600         break;
601       case 1:
602         ok = ( myCurrentLineEdit == myLineEdit1 && ( aGroupType == SMESH::EDGE ||
603                                                      aGroupType == SMESH::FACE ) ) ||
604              ( myCurrentLineEdit == myLineEdit2 && aGroupType == SMESH::NODE )     ||
605              ( myCurrentLineEdit == myLineEdit3 && aGroupType != SMESH::NODE );
606         break;
607       case 2:
608         ok = ( aGroupType != SMESH::NODE );
609         break;
610       case 3:
611         ok = ( aGroupType == SMESH::VOLUME || 
612                aGroupType == SMESH::FACE );
613         break;
614       }
615     }
616     if ( ok ) aGroups << aGroup;
617   }
618
619   // Clear current field
620   myCurrentLineEdit->clear();
621
622   if ( ok && !aGroups.isEmpty() ) {
623     if      ( myCurrentLineEdit == myLineEdit1 ) myGroups1 = aGroups;
624     else if ( myCurrentLineEdit == myLineEdit2 ) myGroups2 = aGroups;
625     else if ( myCurrentLineEdit == myLineEdit3 ) myGroups3 = aGroups;
626     CORBA::String_var name = aGroups[0]->GetName();
627     myCurrentLineEdit->setText( aGroups.count() == 1 ? QString(name).trimmed() : 
628                                 QObject::tr( "SMESH_OBJECTS_SELECTED" ).arg( aGroups.count() ) );
629   }
630   else {
631     if      ( myCurrentLineEdit == myLineEdit1 ) myGroups1.clear();
632     else if ( myCurrentLineEdit == myLineEdit2 ) myGroups2.clear();
633     else if ( myCurrentLineEdit == myLineEdit3 ) myGroups3.clear();
634     myCurrentLineEdit->clear();
635   }
636   // Enable/disable "Apply and Close" and "Apply" buttons
637   updateButtons();
638 }
639
640 /*!
641  * \brief Enable/disable "Apply and Close" and "Apply" buttons
642  */
643 void SMESHGUI_DuplicateNodesDlg::updateButtons()
644 {
645   bool isDataValid = isValid();
646   myButtonOk->setEnabled( isDataValid );
647   myButtonApply->setEnabled( isDataValid );
648
649   int operationMode = myGroupConstructors->checkedId();
650   myGenerateButton3->setEnabled( operationMode <= 1 && !myGroups1.empty() );
651 }
652
653 /*!
654   \brief  SLOT called when selection button clicked.
655 */
656 void SMESHGUI_DuplicateNodesDlg::onEditCurrentArgument()
657 {
658   QPushButton* send = (QPushButton*)sender();
659   
660   // Set current field for edition
661   if (send == mySelectButton1) {
662     myCurrentLineEdit = myLineEdit1;
663   } 
664   else if (send == mySelectButton2) {
665     myCurrentLineEdit = myLineEdit2;
666   }
667   else if (send == mySelectButton3) {
668     myCurrentLineEdit = myLineEdit3;
669   }
670   
671   myCurrentLineEdit->setFocus();
672   onSelectionChanged();
673 }
674
675 /*!
676   \brief Check if the input data is valid.
677   \return \c true if the data is valid
678 */
679 bool SMESHGUI_DuplicateNodesDlg::isValid()
680 {
681   switch( myGroupConstructors->checkedId() )
682   {
683   case 1:  return ( !myGroups1.isEmpty() && !myGroups3.isEmpty()  );
684   case 3:  return ( myGroups1.count() > ( myCheckBox2->isChecked() ? 0 : 1 ));
685   default: return !myGroups1.isEmpty();
686   }
687   return false;
688 }
689
690 /*!
691   \brief SLOT called when dialog should be deactivated.
692 */
693 void SMESHGUI_DuplicateNodesDlg::onDeactivate()
694 {
695   if (isEnabled()) {
696     mySelectionMgr->clearFilters();
697     setEnabled(false);
698     mySMESHGUI->ResetState();
699     mySMESHGUI->SetActiveDialogBox(0);
700   }
701 }
702
703 /*!
704   \brief SLOT called when Generate button is clicked
705 */
706 void SMESHGUI_DuplicateNodesDlg::onGenerate()
707 {
708   if ( SMESHGUI::isStudyLocked() )
709     return;
710
711   SUIT_OverrideCursor aWaitCursor;
712   BusyLocker lock( myBusy );
713
714   try {
715     SMESH::SMESH_Mesh_var             aMesh = myGroups1[0]->GetMesh();
716     SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
717
718     SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
719     g1->length( myGroups1.count() );
720     for ( int i = 0; i < myGroups1.count(); i++ )
721       g1[i] = myGroups1[i];
722     SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups();
723     g2->length( myGroups2.count() );
724     for ( int i = 0; i < myGroups2.count(); i++ )
725       g2[i] = myGroups2[i];
726
727     SMESH::ListOfGroups_var newGroups =
728       aMeshEditor->AffectedElemGroupsInRegion( g1, g2, GEOM::GEOM_Object::_nil() );
729
730     QString text;
731     switch ( newGroups->length() ) {
732     case 0:  break;
733     case 1:  text = SMESH::toQStr( newGroups[0]->GetName() ); break;
734     default: text = tr( "SMESH_OBJECTS_SELECTED" ).arg( newGroups->length() );
735     }
736     myLineEdit3->setText( text );
737
738     myGroups3.clear();
739     for ( CORBA::ULong i = 0; i < newGroups->length(); ++i )
740       myGroups3 << SMESH::SMESH_GroupBase::_duplicate( newGroups[i] );
741   }
742   catch (const SALOME::SALOME_Exception& S_ex) {
743     SalomeApp_Tools::QtCatchCorbaException(S_ex);
744   }
745   catch ( const std::exception& exc ) {
746     INFOS( "Follow exception was caught:\n\t" << exc.what() );
747   }
748   catch (...) {
749     INFOS( "Unknown exception was caught !!!" );
750   }
751
752   mySMESHGUI->updateObjBrowser(true);
753   updateButtons();
754 }
755
756 /*!
757   \brief Receive dialog enter events.
758   Activates the dialog when the mouse cursor enters.
759   Reimplemented from QWidget class.
760 */
761 void SMESHGUI_DuplicateNodesDlg::enterEvent (QEvent*)
762 {
763   if ( !isEnabled() ) {
764     mySMESHGUI->EmitSignalDeactivateDialog();
765     setEnabled(true);
766     mySMESHGUI->SetActiveDialogBox((QDialog*)this);
767     
768     // Set selection mode
769     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
770       aViewWindow->SetSelectionMode(ActorSelection);
771     mySelectionMgr->installFilter(new SMESH_TypeFilter (SMESH::GROUP));
772   }
773 }
774
775 /*!
776   \brief Receive key press events.
777   Reimplemented from QWidget class.
778 */
779 void SMESHGUI_DuplicateNodesDlg::keyPressEvent( QKeyEvent* e )
780 {
781   QDialog::keyPressEvent( e );
782   if ( e->isAccepted() )
783     return;
784
785   if ( e->key() == Qt::Key_F1 ) {
786     e->accept();
787     onHelp();
788   }
789 }
790
791 /*!
792   \brief Show the dialog help page.
793 */
794 void SMESHGUI_DuplicateNodesDlg::onHelp()
795 {
796   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
797   if (app) 
798     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
799   else {
800     QString platform;
801 #ifdef WIN32
802     platform = "winapplication";
803 #else
804     platform = "application";
805 #endif
806     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
807                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
808                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
809                                                                  platform)).
810                              arg(myHelpFileName));
811   }
812 }