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