Salome HOME
Merge changes from 'master' branch.
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_DuplicateNodesDlg.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // SMESH SMESHGUI : GUI for SMESH component
24 // File   : SMESHGUI_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
169   myCheckBox1 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_ELEMENTS"), myGroupArguments);
170   myCheckBox2 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_NODES"), myGroupArguments);
171
172   aGroupArgumentsLayout->addWidget(myTextLabel1,    0, 0);
173   aGroupArgumentsLayout->addWidget(mySelectButton1, 0, 1);
174   aGroupArgumentsLayout->addWidget(myLineEdit1,     0, 2);
175   aGroupArgumentsLayout->addWidget(myTextLabel2,    1, 0);
176   aGroupArgumentsLayout->addWidget(mySelectButton2, 1, 1);
177   aGroupArgumentsLayout->addWidget(myLineEdit2,     1, 2);
178   aGroupArgumentsLayout->addWidget(myTextLabel3,    2, 0);
179   aGroupArgumentsLayout->addWidget(mySelectButton3, 2, 1);
180   aGroupArgumentsLayout->addWidget(myLineEdit3,     2, 2);
181   aGroupArgumentsLayout->addWidget(myCheckBox1, 3, 0);
182   aGroupArgumentsLayout->addWidget(myCheckBox2, 4, 0);
183   aGroupArgumentsLayout->setRowStretch(5, 1);
184   
185   // Buttons
186   QGroupBox* aGroupButtons = new QGroupBox(this);
187   QHBoxLayout* aGroupButtonsLayout = new QHBoxLayout(aGroupButtons);
188   aGroupButtonsLayout->setSpacing(SPACING);
189   aGroupButtonsLayout->setMargin(MARGIN);
190
191   myButtonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), aGroupButtons);
192   myButtonOk->setAutoDefault(true);
193   myButtonOk->setDefault(true);
194   myButtonApply = new QPushButton(tr("SMESH_BUT_APPLY"), aGroupButtons);
195   myButtonApply->setAutoDefault(true);
196   myButtonClose = new QPushButton(tr("SMESH_BUT_CLOSE"), aGroupButtons);
197   myButtonClose->setAutoDefault(true);
198   myButtonHelp = new QPushButton(tr("SMESH_BUT_HELP"), aGroupButtons);
199   myButtonHelp->setAutoDefault(true);
200
201   aGroupButtonsLayout->addWidget(myButtonOk);
202   aGroupButtonsLayout->addSpacing(10);
203   aGroupButtonsLayout->addWidget(myButtonApply);
204   aGroupButtonsLayout->addSpacing(10);
205   aGroupButtonsLayout->addStretch();
206   aGroupButtonsLayout->addWidget(myButtonClose);
207   aGroupButtonsLayout->addWidget(myButtonHelp);
208
209   // Add mode selector, arguments and buttons to the main layout
210   aMainLayout->addWidget(aConstructorsBox);
211   aMainLayout->addWidget(myGroupArguments);
212   aMainLayout->addWidget(aGroupButtons);
213   
214   myCheckBox1->setChecked(true);
215   myCheckBox2->setChecked(true);
216
217   // Initialize the dialog
218   Init();
219
220   // Help file name
221   myHelpFileName = "double_nodes_page.html";
222
223   // Signals and slots connections
224   connect(myGroupConstructors, SIGNAL(buttonClicked(int)), SLOT(onConstructorsClicked(int)));
225      
226   connect(mySelectButton1, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
227   connect(mySelectButton2, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
228   connect(mySelectButton3, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
229
230   connect(myCheckBox2,    SIGNAL(stateChanged(int)), SLOT(updateButtons()));
231
232   connect(myButtonOk,     SIGNAL(clicked()), this, SLOT(onOk()));
233   connect(myButtonClose,  SIGNAL(clicked()), this, SLOT(reject()));
234   connect(myButtonApply,  SIGNAL(clicked()), this, SLOT(onApply()));
235   connect(myButtonHelp,   SIGNAL(clicked()), this, SLOT(onHelp()));
236   
237   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionChanged()));
238
239   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(onDeactivate()));
240   connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
241 }
242
243 /*!
244   \brief Destructor
245 */
246 SMESHGUI_DuplicateNodesDlg::~SMESHGUI_DuplicateNodesDlg()
247 {
248 }
249
250 /*!
251   \brief Destructor
252 */
253 void SMESHGUI_DuplicateNodesDlg::Init()
254 {
255   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
256
257   // Set initial parameters
258   myBusy = false;
259   myCurrentLineEdit = myLineEdit1;
260
261   myGroups1.clear();
262   myGroups2.clear();
263   myGroups3.clear();
264   
265   // Set selection mode
266   mySelectionMgr->installFilter(new SMESH_TypeFilter(SMESH::GROUP));
267   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
268     aViewWindow->SetSelectionMode(ActorSelection);
269   
270   // Set construction mode
271   int operationMode = myGroupConstructors->checkedId();
272   if (operationMode < 0) {
273     // The dialog has been just displayed
274     operationMode = 0;
275     myGroupConstructors->button(0)->setChecked(true);
276   }
277   onConstructorsClicked(operationMode);
278 }
279
280 /*!
281   \brief SLOT called to change the dialog operation mode.
282   \param constructorId id of the radio button in mode selector button group
283 */
284 void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
285 {
286   // Clear all fields
287   myLineEdit1->clear();
288   myLineEdit2->clear();
289   myLineEdit3->clear();
290
291   myGroups1.clear();
292   myGroups2.clear();
293   myGroups3.clear();
294
295   // Set the first field as current
296   myCurrentLineEdit = myLineEdit1;
297   myCurrentLineEdit->setFocus();
298
299   switch (constructorId) {
300   case 0:
301     {
302       // Set text to the group of arguments and to the first two labels
303       myGroupArguments->setTitle(tr("DUPLICATION_WITHOUT_ELEMS"));
304       myTextLabel1->setText(tr("GROUP_NODES_TO_DUPLICATE"));
305       myTextLabel2->setText(tr("GROUP_NODES_TO_REPLACE"));
306
307       myCheckBox1->hide();
308       myCheckBox2->show();
309       myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
310       
311       // Hide the third field
312       myTextLabel2->show();
313       mySelectButton2->show();
314       myLineEdit2->show();
315       myTextLabel3->hide();
316       mySelectButton3->hide();
317       myLineEdit3->hide();
318       
319       break;
320     }
321   case 1:
322     {
323       // Set text to the group of arguments and to all the labels
324       myGroupArguments->setTitle(tr("DUPLICATION_WITH_ELEMS"));
325       myTextLabel1->setText(tr("GROUP_ELEMS_TO_DUPLICATE"));
326       myTextLabel2->setText(tr("GROUP_NODES_NOT_DUPLICATE"));
327       myTextLabel3->setText(tr("GROUP_ELEMS_TO_REPLACE"));
328       
329       myCheckBox1->show();
330       myCheckBox2->show();
331       myCheckBox1->setText( tr("CONSTRUCT_NEW_GROUP_ELEMENTS"));
332       myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
333
334       // Show the third field
335       myTextLabel2->show();
336       mySelectButton2->show();
337       myLineEdit2->show();
338       myTextLabel3->show();
339       mySelectButton3->show();
340       myLineEdit3->show();
341
342       break;
343     }
344   case 2:
345     {
346       // Set text to the group of arguments and to all the labels
347       myGroupArguments->setTitle(tr("DUPLICATION_ONLY_ELEMS"));
348       myTextLabel1->setText(tr("GROUP_ELEMS_TO_DUPLICATE"));
349       
350       myCheckBox1->show();
351       myCheckBox1->setText( tr("CONSTRUCT_NEW_GROUP_ELEMENTS"));
352       myCheckBox2->hide();
353
354       // Hide the second and the third field
355       myTextLabel2->hide();
356       mySelectButton2->hide();
357       myLineEdit2->hide();
358       myTextLabel3->hide();
359       mySelectButton3->hide();
360       myLineEdit3->hide();
361
362       break;
363     }
364   case 3:
365     {
366       // Set text to the group of arguments and to all the labels
367       myGroupArguments->setTitle(tr("DUPLICATION_GROUP_BOUNDARY"));
368       myTextLabel1->setText(tr("GROUP_VOLUME_GROUPS"));
369       
370       myCheckBox1->show();
371       myCheckBox2->show();
372       myCheckBox1->setText( tr("CREATE_JOINT_ELEMENTS"));
373       myCheckBox2->setText( tr("ON_ALL_BOUNDARIES"));
374
375       // Hide the second and the third field
376       myTextLabel2->hide();
377       mySelectButton2->hide();
378       myLineEdit2->hide();
379       myTextLabel3->hide();
380       mySelectButton3->hide();
381       myLineEdit3->hide();
382
383       break;
384     }
385   }
386   myGroupArguments->hide();
387   myGroupArguments->show();
388   this->resize(this->sizeHint().width(), this->minimumSizeHint().height());
389   // Process selection
390   onSelectionChanged();
391 }
392
393 /*!
394   \brief SLOT called to apply changes.
395 */
396 bool SMESHGUI_DuplicateNodesDlg::onApply()
397 {
398   if ( SMESHGUI::isStudyLocked() || !isValid() )
399     return false;
400
401   BusyLocker lock( myBusy );
402  
403   bool toCreateElemGroup = myCheckBox1->isChecked();
404   bool toCreateNodeGroup = myCheckBox2->isChecked();
405   int operationMode      = myGroupConstructors->checkedId();
406   
407   // Apply changes
408   bool result = false;
409   SUIT_OverrideCursor aWaitCursor;
410   QStringList anEntryList;
411
412   try {
413     SMESH::SMESH_Mesh_var aMesh = myGroups1[0]->GetMesh();
414     SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
415
416     switch ( operationMode ) {
417     case 0:
418     {
419       SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
420       g1->length( myGroups1.count() );
421       for ( int i = 0; i < myGroups1.count(); i++ )
422         g1[i] = myGroups1[i];
423       SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups();
424       g2->length( myGroups2.count() );
425       for ( int i = 0; i < myGroups2.count(); i++ )
426         g2[i] = myGroups2[i];
427
428       if ( toCreateNodeGroup ) {
429         SMESH::SMESH_GroupBase_var aNewGroup = 
430           aMeshEditor->DoubleNodeGroupsNew( g1.in(), g2.in() );
431         result = !CORBA::is_nil( aNewGroup );
432       }
433       else {
434         result = aMeshEditor->DoubleNodeGroups( g1.in(), g2.in() );
435       }
436       break;
437     }
438     case 1:
439     {
440       SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
441       g1->length( myGroups1.count() );
442       for ( int i = 0; i < myGroups1.count(); i++ )
443         g1[i] = myGroups1[i];
444       SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups();
445       g2->length( myGroups2.count() );
446       for ( int i = 0; i < myGroups2.count(); i++ )
447         g2[i] = myGroups2[i];
448       SMESH::ListOfGroups_var g3 = new SMESH::ListOfGroups();
449       g3->length( myGroups3.count() );
450
451       for ( int i = 0; i < myGroups3.count(); i++ )
452         g3[i] = myGroups3[i];
453       if ( toCreateElemGroup || toCreateNodeGroup ) {
454         SMESH::ListOfGroups_var aNewGroups = 
455           aMeshEditor->DoubleNodeElemGroups2New( g1.in(), g2.in(), g3.in(),
456                                                  toCreateElemGroup, toCreateNodeGroup );
457         result = ( aNewGroups[ !toCreateElemGroup ].in() );
458       }
459       else {
460         result = aMeshEditor->DoubleNodeElemGroups( g1.in(), g2.in(), g3.in() );
461       }
462       break;
463     }
464     case 2:
465     {
466       result = true;
467       QString groupName;
468       if ( toCreateElemGroup )
469         groupName = SMESH::UniqueName("DoubleElements");
470       for ( int i = 0; i < myGroups1.count(); i++ )
471       {
472         SMESH::SMESH_Group_var group =
473           aMeshEditor->DoubleElements( myGroups1[i], groupName.toLatin1().data() );
474         if ( group->_is_nil() )
475         {
476           if ( toCreateElemGroup )
477             result = false;
478         }
479         else
480         {
481           if ( _PTR(SObject) so = SMESH::FindSObject( group ))
482             anEntryList.append( so->GetID().c_str() );
483         }
484       }
485       break;
486     }
487     case 3:
488     {
489       bool createJointElems = myCheckBox1->isChecked();
490       bool onAllBoundaries  = myCheckBox2->isChecked();
491
492       SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
493       g1->length( myGroups1.count() );
494       for ( int i = 0; i < myGroups1.count(); i++ )
495         g1[i] = myGroups1[i];
496
497       result = aMeshEditor->DoubleNodesOnGroupBoundaries( g1.in(), createJointElems, onAllBoundaries );
498
499       break;
500     }
501     } // switch( operationMode )
502   }
503   catch (const SALOME::SALOME_Exception& S_ex) {
504     SalomeApp_Tools::QtCatchCorbaException(S_ex);
505   }
506   catch ( const std::exception& exc ) {
507     INFOS( "Follow exception was cought:\n\t" << exc.what() );
508   }
509   catch (...) {
510     INFOS( "Unknown exception was cought !!!" );
511   }
512
513   if (!result) {
514     SUIT_MessageBox::warning(this,
515                              tr("SMESH_WRN_WARNING"),
516                              tr("SMESH_OPERATION_FAILED"));
517     return false;
518   }
519
520   // Update GUI
521   mySelectionMgr->clearSelected();
522   SMESH::UpdateView();
523   SMESHGUI::Modified();
524   mySMESHGUI->updateObjBrowser(true);
525
526   if ( !anEntryList.isEmpty())
527     if( LightApp_Application* anApp =
528         dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() ))
529       anApp->browseObjects( anEntryList, true, false );
530
531   // Reinitialize the dialog
532   Init();
533
534   return true;
535 }
536
537 /*!
538   \brief SLOT called to apply changes and close the dialog.
539 */
540 void SMESHGUI_DuplicateNodesDlg::onOk()
541 {
542   if (onApply())
543     reject();
544 }
545
546 /*!
547   \brief SLOT called to close the dialog.
548 */
549 void SMESHGUI_DuplicateNodesDlg::reject()
550 {
551   disconnect(mySelectionMgr, 0, this, 0);
552   disconnect(mySMESHGUI, 0, this, 0);
553   mySMESHGUI->ResetState();
554   mySelectionMgr->clearFilters();
555   QDialog::reject();
556 }
557
558 /*!
559   \brief  SLOT called when selection changed.
560 */
561 void SMESHGUI_DuplicateNodesDlg::onSelectionChanged()
562 {
563   if ( myBusy || !isEnabled() ) return;
564   
565   int operationMode = myGroupConstructors->checkedId();
566
567   SALOME_ListIO aList;
568   mySelectionMgr->selectedObjects( aList );
569   //int aNbSel = aList.Extent();
570
571   QList<SMESH::SMESH_GroupBase_var> aGroups;
572
573   SALOME_ListIteratorOfListIO anIter ( aList );
574   bool ok = true;
575   for ( ; anIter.More() && ok; anIter.Next()) {
576     SMESH::SMESH_GroupBase_var aGroup = SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>( anIter.Value() );
577     // check group is selected
578     ok = !CORBA::is_nil( aGroup );
579     // check groups of the same mesh are selected
580     if ( ok ) {
581       SMESH::SMESH_Mesh_var aMesh1;
582       if ( !aGroups.isEmpty() ) aMesh1 = aGroups[0]->GetMesh();
583       SMESH::SMESH_Mesh_var aMesh2 = aGroup->GetMesh();
584       ok = CORBA::is_nil( aMesh1 ) || aMesh1->_is_equivalent( aMesh2 );
585     }
586     // check group of proper type is selected
587     if ( ok ) {
588       SMESH::ElementType aGroupType = aGroup->GetType();
589       switch ( operationMode ) {
590       case 0:
591         ok = ( myCurrentLineEdit == myLineEdit1 && aGroupType == SMESH::NODE ) ||
592              ( myCurrentLineEdit == myLineEdit2 && aGroupType != SMESH::NODE );
593         break;
594       case 1:
595         ok = ( myCurrentLineEdit == myLineEdit1 && ( aGroupType == SMESH::EDGE ||
596                                                      aGroupType == SMESH::FACE ) ) ||
597              ( myCurrentLineEdit == myLineEdit2 && aGroupType == SMESH::NODE )     ||
598              ( myCurrentLineEdit == myLineEdit3 && aGroupType != SMESH::NODE );
599         break;
600       case 2:
601         ok = ( aGroupType != SMESH::NODE );
602         break;
603       case 3:
604         ok = ( aGroupType == SMESH::VOLUME || 
605                aGroupType == SMESH::FACE );
606         break;
607       }
608     }
609     if ( ok ) aGroups << aGroup;
610   }
611
612   // Clear current field
613   myCurrentLineEdit->clear();
614
615   if ( ok && !aGroups.isEmpty() ) {
616     if      ( myCurrentLineEdit == myLineEdit1 ) myGroups1 = aGroups;
617     else if ( myCurrentLineEdit == myLineEdit2 ) myGroups2 = aGroups;
618     else if ( myCurrentLineEdit == myLineEdit3 ) myGroups3 = aGroups;
619     CORBA::String_var name = aGroups[0]->GetName();
620     myCurrentLineEdit->setText( aGroups.count() == 1 ? QString(name).trimmed() : 
621                                 QObject::tr( "SMESH_OBJECTS_SELECTED" ).arg( aGroups.count() ) );
622   }
623   else {
624     if      ( myCurrentLineEdit == myLineEdit1 ) myGroups1.clear();
625     else if ( myCurrentLineEdit == myLineEdit2 ) myGroups2.clear();
626     else if ( myCurrentLineEdit == myLineEdit3 ) myGroups3.clear();
627     myCurrentLineEdit->clear();
628   }
629   // Enable/disable "Apply and Close" and "Apply" buttons
630   updateButtons();
631 }
632
633 /*!
634  * \brief Enable/disable "Apply and Close" and "Apply" buttons
635  */
636 void SMESHGUI_DuplicateNodesDlg::updateButtons()
637 {
638   bool isDataValid = isValid();
639   myButtonOk->setEnabled( isDataValid );
640   myButtonApply->setEnabled( isDataValid );
641 }
642
643 /*!
644   \brief  SLOT called when selection button clicked.
645 */
646 void SMESHGUI_DuplicateNodesDlg::onEditCurrentArgument()
647 {
648   QPushButton* send = (QPushButton*)sender();
649   
650   // Set current field for edition
651   if (send == mySelectButton1) {
652     myCurrentLineEdit = myLineEdit1;
653   } 
654   else if (send == mySelectButton2) {
655     myCurrentLineEdit = myLineEdit2;
656   }
657   else if (send == mySelectButton3) {
658     myCurrentLineEdit = myLineEdit3;
659   }
660   
661   myCurrentLineEdit->setFocus();
662   onSelectionChanged();
663 }
664
665 /*!
666   \brief Check if the input data is valid.
667   \return \c true if the data is valid
668 */
669 bool SMESHGUI_DuplicateNodesDlg::isValid()
670 {
671   switch( myGroupConstructors->checkedId() )
672   {
673   case 1:  return ( !myGroups1.isEmpty() && !myGroups3.isEmpty()  );
674   case 3:  return ( myGroups1.count() > ( myCheckBox2->isChecked() ? 0 : 1 ));
675   default: return !myGroups1.isEmpty();
676   }
677   return false;
678 }
679
680 /*!
681   \brief SLOT called when dialog shoud be deativated.
682 */
683 void SMESHGUI_DuplicateNodesDlg::onDeactivate()
684 {
685   if (isEnabled()) {
686     mySelectionMgr->clearFilters();
687     setEnabled(false);
688     mySMESHGUI->ResetState();
689     mySMESHGUI->SetActiveDialogBox(0);
690   }
691 }
692
693 /*!
694   \brief Receive dialog enter events.
695   Activates the dialog when the mouse cursor enters.
696   Reimplemented from QWidget class.
697 */
698 void SMESHGUI_DuplicateNodesDlg::enterEvent (QEvent*)
699 {
700   if ( !isEnabled() ) {
701     mySMESHGUI->EmitSignalDeactivateDialog();
702     setEnabled(true);
703     mySMESHGUI->SetActiveDialogBox((QDialog*)this);
704     
705     // Set selection mode
706     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
707       aViewWindow->SetSelectionMode(ActorSelection);
708     mySelectionMgr->installFilter(new SMESH_TypeFilter (SMESH::GROUP));
709   }
710 }
711
712 /*!
713   \brief Receive key press events.
714   Reimplemented from QWidget class.
715 */
716 void SMESHGUI_DuplicateNodesDlg::keyPressEvent( QKeyEvent* e )
717 {
718   QDialog::keyPressEvent( e );
719   if ( e->isAccepted() )
720     return;
721
722   if ( e->key() == Qt::Key_F1 ) {
723     e->accept();
724     onHelp();
725   }
726 }
727
728 /*!
729   \brief Show the dialog help page.
730 */
731 void SMESHGUI_DuplicateNodesDlg::onHelp()
732 {
733   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
734   if (app) 
735     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
736   else {
737     QString platform;
738 #ifdef WIN32
739     platform = "winapplication";
740 #else
741     platform = "application";
742 #endif
743     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
744                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
745                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
746                                                                  platform)).
747                              arg(myHelpFileName));
748   }
749 }