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