Salome HOME
0022364: EDF SMESH: Create Mesh dialog box improvement: hide inapplicable algorithms...
[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 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   
134   aConstructorsBoxLayout->addWidget(aRadioButton1);
135   aConstructorsBoxLayout->addWidget(aRadioButton2);
136   aConstructorsBoxLayout->addWidget(aRadioButton3);
137   myGroupConstructors->addButton(aRadioButton1, 0);
138   myGroupConstructors->addButton(aRadioButton2, 1);
139   myGroupConstructors->addButton(aRadioButton3, 2);
140
141   // Arguments
142   myGroupArguments = new QGroupBox(this);
143   QGridLayout* aGroupArgumentsLayout = new QGridLayout(myGroupArguments);
144   aGroupArgumentsLayout->setSpacing(SPACING);
145   aGroupArgumentsLayout->setMargin(MARGIN);
146     
147   myTextLabel1 = new QLabel(myGroupArguments);
148   mySelectButton1 = new QPushButton(myGroupArguments);
149   mySelectButton1->setIcon(iconSelect);
150   myLineEdit1 = new QLineEdit(myGroupArguments);
151   myLineEdit1->setReadOnly(true);
152
153   myTextLabel2 = new QLabel(myGroupArguments);
154   mySelectButton2 = new QPushButton(myGroupArguments);
155   mySelectButton2->setIcon(iconSelect);
156   myLineEdit2 = new QLineEdit(myGroupArguments);
157   myLineEdit2->setReadOnly(true);
158
159   myTextLabel3 = new QLabel(myGroupArguments);
160   mySelectButton3 = new QPushButton(myGroupArguments);
161   mySelectButton3->setIcon(iconSelect);
162   myLineEdit3 = new QLineEdit(myGroupArguments);
163   myLineEdit3->setReadOnly(true);
164
165   myCheckBoxNewElemGroup = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_ELEMENTS"), myGroupArguments);
166   myCheckBoxNewNodeGroup = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_NODES"), myGroupArguments);
167
168   aGroupArgumentsLayout->addWidget(myTextLabel1,    0, 0);
169   aGroupArgumentsLayout->addWidget(mySelectButton1, 0, 1);
170   aGroupArgumentsLayout->addWidget(myLineEdit1,     0, 2);
171   aGroupArgumentsLayout->addWidget(myTextLabel2,    1, 0);
172   aGroupArgumentsLayout->addWidget(mySelectButton2, 1, 1);
173   aGroupArgumentsLayout->addWidget(myLineEdit2,     1, 2);
174   aGroupArgumentsLayout->addWidget(myTextLabel3,    2, 0);
175   aGroupArgumentsLayout->addWidget(mySelectButton3, 2, 1);
176   aGroupArgumentsLayout->addWidget(myLineEdit3,     2, 2);
177   aGroupArgumentsLayout->addWidget(myCheckBoxNewElemGroup, 3, 0);
178   aGroupArgumentsLayout->addWidget(myCheckBoxNewNodeGroup, 4, 0);
179   aGroupArgumentsLayout->setRowStretch(5, 1);
180   
181   // Buttons
182   QGroupBox* aGroupButtons = new QGroupBox(this);
183   QHBoxLayout* aGroupButtonsLayout = new QHBoxLayout(aGroupButtons);
184   aGroupButtonsLayout->setSpacing(SPACING);
185   aGroupButtonsLayout->setMargin(MARGIN);
186
187   myButtonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), aGroupButtons);
188   myButtonOk->setAutoDefault(true);
189   myButtonOk->setDefault(true);
190   myButtonApply = new QPushButton(tr("SMESH_BUT_APPLY"), aGroupButtons);
191   myButtonApply->setAutoDefault(true);
192   myButtonClose = new QPushButton(tr("SMESH_BUT_CLOSE"), aGroupButtons);
193   myButtonClose->setAutoDefault(true);
194   myButtonHelp = new QPushButton(tr("SMESH_BUT_HELP"), aGroupButtons);
195   myButtonHelp->setAutoDefault(true);
196
197   aGroupButtonsLayout->addWidget(myButtonOk);
198   aGroupButtonsLayout->addSpacing(10);
199   aGroupButtonsLayout->addWidget(myButtonApply);
200   aGroupButtonsLayout->addSpacing(10);
201   aGroupButtonsLayout->addStretch();
202   aGroupButtonsLayout->addWidget(myButtonClose);
203   aGroupButtonsLayout->addWidget(myButtonHelp);
204
205   // Add mode selector, arguments and buttons to the main layout
206   aMainLayout->addWidget(aConstructorsBox);
207   aMainLayout->addWidget(myGroupArguments);
208   aMainLayout->addWidget(aGroupButtons);
209   
210   myCheckBoxNewElemGroup->setChecked(true);
211   myCheckBoxNewNodeGroup->setChecked(true);
212
213   // Initialize the dialog
214   Init();
215
216   // Help file name
217   myHelpFileName = "double_nodes_page.html";
218
219   // Signals and slots connections
220   connect(myGroupConstructors, SIGNAL(buttonClicked(int)), SLOT(onConstructorsClicked(int)));
221      
222   connect(mySelectButton1, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
223   connect(mySelectButton2, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
224   connect(mySelectButton3, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
225
226   connect(myButtonOk,     SIGNAL(clicked()), this, SLOT(onOk()));
227   connect(myButtonClose,  SIGNAL(clicked()), this, SLOT(reject()));
228   connect(myButtonApply,  SIGNAL(clicked()), this, SLOT(onApply()));
229   connect(myButtonHelp,   SIGNAL(clicked()), this, SLOT(onHelp()));
230   
231   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionChanged()));
232
233   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(onDeactivate()));
234   connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
235 }
236
237 /*!
238   \brief Destructor
239 */
240 SMESHGUI_DuplicateNodesDlg::~SMESHGUI_DuplicateNodesDlg()
241 {
242 }
243
244 /*!
245   \brief Destructor
246 */
247 void SMESHGUI_DuplicateNodesDlg::Init()
248 {
249   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
250
251   // Set initial parameters
252   myBusy = false;
253   myCurrentLineEdit = myLineEdit1;
254
255   myGroups1.clear();
256   myGroups2.clear();
257   myGroups3.clear();
258   
259   // Set selection mode
260   mySelectionMgr->installFilter(new SMESH_TypeFilter(SMESH::GROUP));
261   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
262     aViewWindow->SetSelectionMode(ActorSelection);
263   
264   // Set construction mode
265   int operationMode = myGroupConstructors->checkedId();
266   if (operationMode < 0) {
267     // The dialog has been just displayed
268     operationMode = 0;
269     myGroupConstructors->button(0)->setChecked(true);
270   }
271   onConstructorsClicked(operationMode);
272 }
273
274 /*!
275   \brief SLOT called to change the dialog operation mode.
276   \param constructorId id of the radio button in mode selector button group
277 */
278 void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
279 {
280   // Clear all fields
281   myLineEdit1->clear();
282   myLineEdit2->clear();
283   myLineEdit3->clear();
284
285   myGroups1.clear();
286   myGroups2.clear();
287   myGroups3.clear();
288
289   // Set the first field as current
290   myCurrentLineEdit = myLineEdit1;
291   myCurrentLineEdit->setFocus();
292
293   switch (constructorId) {
294   case 0:
295     {
296       // Set text to the group of arguments and to the first two labels
297       myGroupArguments->setTitle(tr("DUPLICATION_WITHOUT_ELEMS"));
298       myTextLabel1->setText(tr("GROUP_NODES_TO_DUPLICATE"));
299       myTextLabel2->setText(tr("GROUP_NODES_TO_REPLACE"));
300
301       myCheckBoxNewElemGroup->hide();
302       myCheckBoxNewNodeGroup->show();
303       
304       // Hide the third field
305       myTextLabel2->show();
306       mySelectButton2->show();
307       myLineEdit2->show();
308       myTextLabel3->hide();
309       mySelectButton3->hide();
310       myLineEdit3->hide();
311       
312       break;
313     }
314   case 1:
315     {
316       // Set text to the group of arguments and to all the labels
317       myGroupArguments->setTitle(tr("DUPLICATION_WITH_ELEMS"));
318       myTextLabel1->setText(tr("GROUP_ELEMS_TO_DUPLICATE"));
319       myTextLabel2->setText(tr("GROUP_NODES_NOT_DUPLICATE"));
320       myTextLabel3->setText(tr("GROUP_ELEMS_TO_REPLACE"));
321       
322       myCheckBoxNewElemGroup->show();
323       myCheckBoxNewNodeGroup->show();
324
325       // Show the third field
326       myTextLabel2->show();
327       mySelectButton2->show();
328       myLineEdit2->show();
329       myTextLabel3->show();
330       mySelectButton3->show();
331       myLineEdit3->show();
332
333       break;
334     }
335   case 2:
336     {
337       // Set text to the group of arguments and to all the labels
338       myGroupArguments->setTitle(tr("DUPLICATION_ONLY_ELEMS"));
339       myTextLabel1->setText(tr("GROUP_ELEMS_TO_DUPLICATE"));
340       
341       myCheckBoxNewElemGroup->show();
342       myCheckBoxNewNodeGroup->hide();
343
344       // Hide the second and the third field
345       myTextLabel2->hide();
346       mySelectButton2->hide();
347       myLineEdit2->hide();
348       myTextLabel3->hide();
349       mySelectButton3->hide();
350       myLineEdit3->hide();
351
352       break;
353     }
354   }
355   
356   // Process selection
357   onSelectionChanged();
358 }
359
360 /*!
361   \brief SLOT called to apply changes.
362 */
363 bool SMESHGUI_DuplicateNodesDlg::onApply()
364 {
365   if ( mySMESHGUI->isActiveStudyLocked() || !isValid() )
366     return false;
367
368   BusyLocker lock( myBusy );
369  
370   bool toCreateElemGroup = myCheckBoxNewElemGroup->isChecked();
371   bool toCreateNodeGroup = myCheckBoxNewNodeGroup->isChecked();
372   int operationMode      = myGroupConstructors->checkedId();
373   
374   // Apply changes
375   bool result = false;
376   SUIT_OverrideCursor aWaitCursor;
377   QStringList anEntryList;
378
379   try {
380     SMESH::SMESH_Mesh_var aMesh = myGroups1[0]->GetMesh();
381     SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
382
383     switch ( operationMode ) {
384     case 0:
385     {
386       SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
387       g1->length( myGroups1.count() );
388       for ( int i = 0; i < myGroups1.count(); i++ )
389         g1[i] = myGroups1[i];
390       SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups();
391       g2->length( myGroups2.count() );
392       for ( int i = 0; i < myGroups2.count(); i++ )
393         g2[i] = myGroups2[i];
394
395       if ( toCreateNodeGroup ) {
396         SMESH::SMESH_GroupBase_var aNewGroup = 
397           aMeshEditor->DoubleNodeGroupsNew( g1.in(), g2.in() );
398         result = !CORBA::is_nil( aNewGroup );
399       }
400       else {
401         result = aMeshEditor->DoubleNodeGroups( g1.in(), g2.in() );
402       }
403       break;
404     }
405     case 1:
406     {
407       SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
408       g1->length( myGroups1.count() );
409       for ( int i = 0; i < myGroups1.count(); i++ )
410         g1[i] = myGroups1[i];
411       SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups();
412       g2->length( myGroups2.count() );
413       for ( int i = 0; i < myGroups2.count(); i++ )
414         g2[i] = myGroups2[i];
415       SMESH::ListOfGroups_var g3 = new SMESH::ListOfGroups();
416       g3->length( myGroups3.count() );
417
418       for ( int i = 0; i < myGroups3.count(); i++ )
419         g3[i] = myGroups3[i];
420       if ( toCreateElemGroup || toCreateNodeGroup ) {
421         SMESH::ListOfGroups_var aNewGroups = 
422           aMeshEditor->DoubleNodeElemGroups2New( g1.in(), g2.in(), g3.in(),
423                                                  toCreateElemGroup, toCreateNodeGroup );
424         result = ( aNewGroups[ !toCreateElemGroup ].in() );
425       }
426       else {
427         result = aMeshEditor->DoubleNodeElemGroups( g1.in(), g2.in(), g3.in() );
428       }
429       break;
430     }
431     case 2:
432     {
433       result = true;
434       QString groupName;
435       if ( toCreateElemGroup )
436         groupName = SMESH::UniqueName("DoubleElements");
437       for ( int i = 0; i < myGroups1.count(); i++ )
438       {
439         SMESH::SMESH_Group_var group =
440           aMeshEditor->DoubleElements( myGroups1[i], groupName.toLatin1().data() );
441         if ( group->_is_nil() )
442         {
443           if ( toCreateElemGroup )
444             result = false;
445         }
446         else
447         {
448           if ( _PTR(SObject) so = SMESH::FindSObject( group ))
449             anEntryList.append( so->GetID().c_str() );
450         }
451       }
452       break;
453     }
454     }
455   }
456   catch (const SALOME::SALOME_Exception& S_ex) {
457     SalomeApp_Tools::QtCatchCorbaException(S_ex);
458   }
459   catch ( const std::exception& exc ) {
460     INFOS( "Follow exception was cought:\n\t" << exc.what() );
461   } 
462   catch (...) {
463     INFOS( "Unknown exception was cought !!!" );
464   }
465
466   if (!result) {
467     SUIT_MessageBox::warning(this,
468                              tr("SMESH_WRN_WARNING"),
469                              tr("SMESH_OPERATION_FAILED"));
470     return false;
471   }
472
473   // Update GUI
474   mySelectionMgr->clearSelected();
475   SMESH::UpdateView();
476   SMESHGUI::Modified();
477   mySMESHGUI->updateObjBrowser(true);
478
479   if ( !anEntryList.isEmpty())
480     if( LightApp_Application* anApp =
481         dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() ))
482       anApp->browseObjects( anEntryList, true, false );
483
484   // Reinitialize the dialog
485   Init();
486
487   return true;
488 }
489
490 /*!
491   \brief SLOT called to apply changes and close the dialog.
492 */
493 void SMESHGUI_DuplicateNodesDlg::onOk()
494 {
495   if (onApply())
496     reject();
497 }
498
499 /*!
500   \brief SLOT called to close the dialog.
501 */
502 void SMESHGUI_DuplicateNodesDlg::reject()
503 {
504   disconnect(mySelectionMgr, 0, this, 0);
505   disconnect(mySMESHGUI, 0, this, 0);
506   mySMESHGUI->ResetState();
507   mySelectionMgr->clearFilters();
508   QDialog::reject();
509 }
510
511 /*!
512   \brief  SLOT called when selection changed.
513 */
514 void SMESHGUI_DuplicateNodesDlg::onSelectionChanged()
515 {
516   if ( myBusy || !isEnabled() ) return;
517   
518   int operationMode = myGroupConstructors->checkedId();
519
520   SALOME_ListIO aList;
521   mySelectionMgr->selectedObjects( aList );
522   //int aNbSel = aList.Extent();
523
524   QList<SMESH::SMESH_GroupBase_var> aGroups;
525
526   SALOME_ListIteratorOfListIO anIter ( aList );
527   bool ok = true;
528   for ( ; anIter.More() && ok; anIter.Next()) {
529     SMESH::SMESH_GroupBase_var aGroup = SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>( anIter.Value() );
530     // check group is selected
531     ok = !CORBA::is_nil( aGroup );
532     // check groups of the same mesh are selected
533     if ( ok ) {
534       SMESH::SMESH_Mesh_var aMesh1;
535       if ( !aGroups.isEmpty() ) aMesh1 = aGroups[0]->GetMesh();
536       SMESH::SMESH_Mesh_var aMesh2 = aGroup->GetMesh();
537       ok = CORBA::is_nil( aMesh1 ) || aMesh1->_is_equivalent( aMesh2 );
538     }
539     // check group of proper type is selected
540     if ( ok ) {
541       SMESH::ElementType aGroupType = aGroup->GetType();
542       switch ( operationMode ) {
543       case 0:
544         ok = ( myCurrentLineEdit == myLineEdit1 && aGroupType == SMESH::NODE ) ||
545              ( myCurrentLineEdit == myLineEdit2 && aGroupType != SMESH::NODE );
546         break;
547       case 1:
548         ok = ( myCurrentLineEdit == myLineEdit1 && ( aGroupType == SMESH::EDGE ||
549                                                      aGroupType == SMESH::FACE ) ) ||
550              ( myCurrentLineEdit == myLineEdit2 && aGroupType == SMESH::NODE )     ||
551              ( myCurrentLineEdit == myLineEdit3 && aGroupType != SMESH::NODE );
552         break;
553       case 2:
554         ok = ( aGroupType != SMESH::NODE );
555         break;
556       }
557     }
558     if ( ok ) aGroups << aGroup;
559   }
560
561   // Clear current field
562   myCurrentLineEdit->clear();
563
564   if ( ok && !aGroups.isEmpty() ) {
565     if      ( myCurrentLineEdit == myLineEdit1 ) myGroups1 = aGroups;
566     else if ( myCurrentLineEdit == myLineEdit2 ) myGroups2 = aGroups;
567     else if ( myCurrentLineEdit == myLineEdit3 ) myGroups3 = aGroups;
568     CORBA::String_var name = aGroups[0]->GetName();
569     myCurrentLineEdit->setText( aGroups.count() == 1 ? QString(name).trimmed() : 
570                                 QObject::tr( "SMESH_OBJECTS_SELECTED" ).arg( aGroups.count() ) );
571   }
572   else {
573     if      ( myCurrentLineEdit == myLineEdit1 ) myGroups1.clear();
574     else if ( myCurrentLineEdit == myLineEdit2 ) myGroups2.clear();
575     else if ( myCurrentLineEdit == myLineEdit3 ) myGroups3.clear();
576     myCurrentLineEdit->clear();
577   }
578
579   // Enable/disable "Apply and Close" and "Apply" buttons
580   bool isDataValid = isValid();
581   myButtonOk->setEnabled( isDataValid );
582   myButtonApply->setEnabled( isDataValid );
583 }
584
585 /*!
586   \brief  SLOT called when selection button clicked.
587 */
588 void SMESHGUI_DuplicateNodesDlg::onEditCurrentArgument()
589 {
590   QPushButton* send = (QPushButton*)sender();
591   
592   // Set current field for edition
593   if (send == mySelectButton1) {
594     myCurrentLineEdit = myLineEdit1;
595   } 
596   else if (send == mySelectButton2) {
597     myCurrentLineEdit = myLineEdit2;
598   }
599   else if (send == mySelectButton3) {
600     myCurrentLineEdit = myLineEdit3;
601   }
602   
603   myCurrentLineEdit->setFocus();
604   onSelectionChanged();
605 }
606
607 /*!
608   \brief Check if the input data is valid.
609   \return \c true if the data is valid
610 */
611 bool SMESHGUI_DuplicateNodesDlg::isValid()
612 {
613   return myGroupConstructors->checkedId() == 1 ?
614     ( !myGroups1.isEmpty() && !myGroups3.isEmpty()  ) :
615     ( !myGroups1.isEmpty() );
616 }
617
618
619 /*!
620   \brief SLOT called when dialog shoud be deativated.
621 */
622 void SMESHGUI_DuplicateNodesDlg::onDeactivate()
623 {
624   if (isEnabled()) {
625     mySelectionMgr->clearFilters();
626     setEnabled(false);
627     mySMESHGUI->ResetState();
628     mySMESHGUI->SetActiveDialogBox(0);
629   }
630 }
631
632 /*!
633   \brief Receive dialog enter events.
634   Activates the dialog when the mouse cursor enters.
635   Reimplemented from QWidget class.
636 */
637 void SMESHGUI_DuplicateNodesDlg::enterEvent (QEvent*)
638 {
639   if ( !isEnabled() ) {
640     mySMESHGUI->EmitSignalDeactivateDialog();
641     setEnabled(true);
642     mySMESHGUI->SetActiveDialogBox((QDialog*)this);
643     
644     // Set selection mode
645     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
646       aViewWindow->SetSelectionMode(ActorSelection);
647     mySelectionMgr->installFilter(new SMESH_TypeFilter (SMESH::GROUP));
648   }
649 }
650
651 /*!
652   \brief Receive key press events.
653   Reimplemented from QWidget class.
654 */
655 void SMESHGUI_DuplicateNodesDlg::keyPressEvent( QKeyEvent* e )
656 {
657   QDialog::keyPressEvent( e );
658   if ( e->isAccepted() )
659     return;
660
661   if ( e->key() == Qt::Key_F1 ) {
662     e->accept();
663     onHelp();
664   }
665 }
666
667 /*!
668   \brief Show the dialog help page.
669 */
670 void SMESHGUI_DuplicateNodesDlg::onHelp()
671 {
672   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
673   if (app) 
674     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
675   else {
676     QString platform;
677 #ifdef WIN32
678     platform = "winapplication";
679 #else
680     platform = "application";
681 #endif
682     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
683                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
684                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
685                                                                  platform)).
686                              arg(myHelpFileName));
687   }
688 }