Salome HOME
IMP 23078: [CEA 1498] Sewing of meshes without having to set the nodes ids
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MergeDlg.cxx
1 // Copyright (C) 2007-2015  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_MergeDlg.cxx
25 // Author : Open CASCADE S.A.S.
26 // SMESH includes
27 //
28 #include "SMESHGUI_MergeDlg.h"
29
30 #include "SMESHGUI.h"
31 #include "SMESHGUI_IdPreview.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_SpinBox.h"
34 #include "SMESHGUI_Utils.h"
35 #include "SMESHGUI_VTKUtils.h"
36
37 #include <SMESH_Actor.h>
38 #include <SMESH_TypeFilter.hxx>
39 #include <SMESH_LogicalFilter.hxx>
40 #include <SMDS_Mesh.hxx>
41
42 // SALOME GUI includes
43 #include <SUIT_Desktop.h>
44 #include <SUIT_ResourceMgr.h>
45 #include <SUIT_Session.h>
46 #include <SUIT_MessageBox.h>
47 #include <SUIT_OverrideCursor.h>
48
49 #include <LightApp_Application.h>
50 #include <LightApp_SelectionMgr.h>
51
52 #include <SVTK_ViewModel.h>
53 #include <SVTK_ViewWindow.h>
54 #include <SALOME_ListIO.hxx>
55
56 // OCCT includes
57 #include <TColStd_MapOfInteger.hxx>
58 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
59
60 // IDL includes
61 #include <SALOMEconfig.h>
62 #include CORBA_SERVER_HEADER(SMESH_Group)
63 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
64
65 // Qt includes
66 #include <QApplication>
67 #include <QButtonGroup>
68 #include <QCheckBox>
69 #include <QGridLayout>
70 #include <QGroupBox>
71 #include <QHBoxLayout>
72 #include <QKeyEvent>
73 #include <QLabel>
74 #include <QLineEdit>
75 #include <QListWidget>
76 #include <QPushButton>
77 #include <QRadioButton>
78 #include <QVBoxLayout>
79
80 #define SPACING 6
81 #define MARGIN  11
82
83 namespace
84 {
85   enum ActionType { MERGE_NODES, MERGE_ELEMENTS, TYPE_AUTO=0, TYPE_MANUAL };
86 }
87
88
89 QPixmap SMESHGUI_MergeDlg::IconFirst()
90 {
91   static const char * iconFirst[] = {
92     "18 10 2 1",
93     "       g None",
94     ".      g #000000",
95     "         .     .  ",
96     "  ..    ..    ..  ",
97     "  ..   ...   ...  ",
98     "  ..  ....  ....  ",
99     "  .. ..... .....  ",
100     "  .. ..... .....  ",
101     "  ..  ....  ....  ",
102     "  ..   ...   ...  ",
103     "  ..    ..    ..  ",
104     "         .     .  "};
105   return iconFirst;
106 }
107
108 //=================================================================================
109 // class    : SMESHGUI_MergeDlg()
110 // purpose  :
111 //=================================================================================
112 SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
113   : QDialog(SMESH::GetDesktop(theModule)),
114     mySMESHGUI(theModule),
115     mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
116     myAction(theAction)
117 {
118   setModal(false);
119   setAttribute(Qt::WA_DeleteOnClose, true);
120   setWindowTitle(myAction == MERGE_ELEMENTS ? tr("SMESH_MERGE_ELEMENTS") : tr("SMESH_MERGE_NODES"));
121
122   myIdPreview = new SMESHGUI_IdPreview(SMESH::GetViewWindow( mySMESHGUI ));
123
124   SUIT_ResourceMgr* aResMgr = SMESH::GetResourceMgr( mySMESHGUI );
125   QPixmap IconMergeNodes (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_MERGE_NODES")));
126   QPixmap IconMergeElems (aResMgr->loadPixmap("SMESH", tr("ICON_DLG_MERGE_ELEMENTS")));
127   QPixmap IconSelect     (aResMgr->loadPixmap("SMESH", tr("ICON_SELECT")));
128   QPixmap IconAdd        (aResMgr->loadPixmap("SMESH", tr("ICON_APPEND")));
129   QPixmap IconRemove     (aResMgr->loadPixmap("SMESH", tr("ICON_REMOVE")));
130
131   setSizeGripEnabled(true);
132
133   QVBoxLayout* DlgLayout = new QVBoxLayout(this);
134   DlgLayout->setSpacing(SPACING);
135   DlgLayout->setMargin(MARGIN);
136
137   /***************************************************************/
138   GroupConstructors = new QGroupBox(myAction == MERGE_ELEMENTS ? 
139                                     tr("SMESH_MERGE_ELEMENTS") : 
140                                     tr("SMESH_MERGE_NODES"), 
141                                     this);
142
143   QButtonGroup* ButtonGroup = new QButtonGroup(this);
144   QHBoxLayout* GroupConstructorsLayout = new QHBoxLayout(GroupConstructors);
145   GroupConstructorsLayout->setSpacing(SPACING);
146   GroupConstructorsLayout->setMargin(MARGIN);
147
148   RadioButton = new QRadioButton(GroupConstructors);
149   RadioButton->setIcon(myAction == MERGE_ELEMENTS ? IconMergeElems : IconMergeNodes);
150   RadioButton->setChecked(true);
151   GroupConstructorsLayout->addWidget(RadioButton);
152   ButtonGroup->addButton(RadioButton, 0);
153
154   /***************************************************************/
155   // Controls for mesh defining
156   GroupMesh = new QGroupBox(tr("SMESH_SELECT_WHOLE_MESH"), this);
157   QHBoxLayout* GroupMeshLayout = new QHBoxLayout(GroupMesh);
158   GroupMeshLayout->setSpacing(SPACING);
159   GroupMeshLayout->setMargin(MARGIN);
160
161   TextLabelName = new QLabel(tr("SMESH_NAME"), GroupMesh);
162   SelectMeshButton = new QPushButton(GroupMesh);
163   SelectMeshButton->setIcon(IconSelect);
164   LineEditMesh = new QLineEdit(GroupMesh);
165   LineEditMesh->setReadOnly(true);
166
167   GroupMeshLayout->addWidget(TextLabelName);
168   GroupMeshLayout->addWidget(SelectMeshButton);
169   GroupMeshLayout->addWidget(LineEditMesh);
170
171   /***************************************************************/
172   // Controls for switch dialog behaviour (myTypeId)
173
174   TypeBox = new QGroupBox( tr( "SMESH_MODE" ), this );
175   GroupType = new QButtonGroup( this );
176   QHBoxLayout* aTypeBoxLayout = new QHBoxLayout( TypeBox );
177   aTypeBoxLayout->setMargin( MARGIN );
178   aTypeBoxLayout->setSpacing( SPACING );
179
180   QRadioButton* rb1 = new QRadioButton( tr( "SMESH_AUTOMATIC" ), TypeBox );
181   QRadioButton* rb2 = new QRadioButton( tr( "SMESH_MANUAL" ),   TypeBox );
182   GroupType->addButton( rb1, 0 );
183   GroupType->addButton( rb2, 1 );
184   aTypeBoxLayout->addWidget( rb1 );
185   aTypeBoxLayout->addWidget( rb2 );
186
187   myTypeId = TYPE_AUTO;
188
189   /***************************************************************/
190   // Controls for coincident elements detecting
191   GroupCoincident = new QGroupBox(myAction == MERGE_ELEMENTS ? 
192                                   tr("COINCIDENT_ELEMENTS") : 
193                                   tr("COINCIDENT_NODES"), 
194                                   this);
195
196   QVBoxLayout* aCoincidentLayout = new QVBoxLayout(GroupCoincident);
197   aCoincidentLayout->setSpacing(SPACING);
198   aCoincidentLayout->setMargin(MARGIN);
199
200   if (myAction == MERGE_NODES) // case merge nodes
201   {
202     QWidget* foo = new QWidget(GroupCoincident);
203     TextLabelTolerance = new QLabel(tr("SMESH_TOLERANCE"), foo);
204     SpinBoxTolerance = new SMESHGUI_SpinBox(foo);
205     SpinBoxTolerance->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
206
207     SeparateCornersAndMedium = new QCheckBox(tr("SEPARATE_CORNERS_AND_MEDIUM"), foo);
208     SeparateCornersAndMedium->setEnabled( false );
209
210     GroupExclude = new QGroupBox(tr("EXCLUDE_GROUPS"), foo);
211     GroupExclude->setCheckable( true );
212     GroupExclude->setChecked( false );
213     ListExclude = new QListWidget( GroupExclude );
214     QVBoxLayout* GroupExcludeLayout = new QVBoxLayout(GroupExclude);
215     GroupExcludeLayout->setSpacing(SPACING);
216     GroupExcludeLayout->setMargin(MARGIN);
217     GroupExcludeLayout->addWidget(ListExclude);
218
219     QGroupBox*  GroupKeep = new QGroupBox(tr("KEEP_NODES"), foo);
220     SelectKeepNodesButton = new QPushButton( GroupKeep );
221     SelectKeepNodesButton->setIcon( IconSelect );
222     QLabel*       selectLabel = new QLabel(tr("SELECT"));
223     QRadioButton*   idsButton = new QRadioButton(tr("NODE_IDS"), GroupKeep);
224     QRadioButton* groupButton = new QRadioButton(tr("GROUP_SUBMESH"), GroupKeep);
225     KeepFromButGroup = new QButtonGroup( this );
226     KeepFromButGroup->addButton( idsButton,   0 );
227     KeepFromButGroup->addButton( groupButton, 1 );
228     groupButton->setChecked( true );
229     KeepList = new QListWidget( GroupKeep );
230     KeepList->setSelectionMode(QAbstractItemView::ExtendedSelection);
231     KeepList->setFlow(QListView::TopToBottom);
232     AddKeepNodesButton    = new QPushButton(tr("SMESH_BUT_ADD"), GroupKeep );
233     RemoveKeepNodesButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupKeep );
234     QGridLayout* GroupKeepLayout = new QGridLayout(GroupKeep);
235     GroupKeepLayout->setSpacing( SPACING );
236     GroupKeepLayout->setMargin ( MARGIN );
237     GroupKeepLayout->addWidget( SelectKeepNodesButton, 0, 0 );
238     GroupKeepLayout->addWidget( selectLabel,           0, 1 );
239     GroupKeepLayout->addWidget( idsButton,             0, 2 );
240     GroupKeepLayout->addWidget( groupButton,           0, 3, 1, 2 );
241     GroupKeepLayout->addWidget( KeepList,              1, 0, 2, 4 );
242     GroupKeepLayout->addWidget( AddKeepNodesButton,    1, 4, 1, 1 );
243     GroupKeepLayout->addWidget( RemoveKeepNodesButton, 2, 4, 1, 1 );
244
245     QGridLayout* fooLayout = new QGridLayout( foo );
246     fooLayout->setSpacing(SPACING);
247     fooLayout->setMargin(0);
248     fooLayout->addWidget(TextLabelTolerance,       0, 0 );
249     fooLayout->addWidget(SpinBoxTolerance,         0, 1 );
250     fooLayout->addWidget(SeparateCornersAndMedium, 1, 0 );
251     fooLayout->addWidget(GroupExclude,             2, 0, 1, 2 );
252     fooLayout->addWidget(GroupKeep,                3, 0, 1, 2 );
253     aCoincidentLayout->addWidget(foo);
254
255     // Costruction of the logical filter
256     QList<SUIT_SelectionFilter*> aListOfFilters;
257     aListOfFilters << new SMESH_TypeFilter (SMESH::SUBMESH)
258                    << new SMESH_TypeFilter (SMESH::GROUP);
259     mySubMeshOrGroupFilter =
260       new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR, /*takeOwnership=*/true);
261   }
262   else {
263     TextLabelTolerance     = 0;
264     SpinBoxTolerance       = 0;
265     GroupExclude           = 0;
266     ListExclude            = 0;
267     KeepFromButGroup       = 0;
268     SelectKeepNodesButton  = 0;
269     AddKeepNodesButton     = 0;
270     RemoveKeepNodesButton  = 0;
271     KeepList               = 0;
272     mySubMeshOrGroupFilter = 0;
273   }
274
275   GroupCoincidentWidget = new QWidget(GroupCoincident);
276   QGridLayout* GroupCoincidentLayout = new QGridLayout(GroupCoincidentWidget);
277   GroupCoincidentLayout->setSpacing(SPACING);
278   GroupCoincidentLayout->setMargin(0);
279
280   ListCoincident = new QListWidget(GroupCoincidentWidget);
281   ListCoincident->setSelectionMode(QListWidget::ExtendedSelection);
282
283   DetectButton      = new QPushButton(tr("DETECT"),           GroupCoincidentWidget);
284   AddGroupButton    = new QPushButton(tr("SMESH_BUT_ADD"),    GroupCoincidentWidget);
285   RemoveGroupButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupCoincidentWidget);
286
287   SelectAllCB = new QCheckBox(tr("SELECT_ALL"), GroupCoincidentWidget);
288   ShowIDs = new QCheckBox(myAction == MERGE_ELEMENTS ? tr("SHOW_ELEMS_IDS") : tr("SHOW_NODES_IDS"), GroupCoincidentWidget);
289
290   GroupCoincidentLayout->addWidget(ListCoincident,    0,   0, 4, 2);
291   GroupCoincidentLayout->addWidget(DetectButton,      0,   2);
292   GroupCoincidentLayout->addWidget(AddGroupButton,    2, 2);
293   GroupCoincidentLayout->addWidget(RemoveGroupButton, 3, 2);
294   GroupCoincidentLayout->addWidget(SelectAllCB,       4, 0);
295   GroupCoincidentLayout->addWidget(ShowIDs,           4, 1);
296   GroupCoincidentLayout->setRowMinimumHeight(1, 10);
297   GroupCoincidentLayout->setRowStretch(1, 5);
298
299   aCoincidentLayout->addWidget(GroupCoincidentWidget);
300
301   /***************************************************************/
302   // Controls for editing the selected group
303   GroupEdit = new QGroupBox(tr("EDIT_SELECTED_GROUP"), this);
304   QGridLayout* GroupEditLayout = new QGridLayout(GroupEdit);
305   GroupEditLayout->setSpacing(SPACING);
306   GroupEditLayout->setMargin(MARGIN);
307
308   ListEdit = new QListWidget(GroupEdit);
309   //ListEdit->setRowMode(QListBox::FixedNumber);
310   //ListEdit->setHScrollBarMode(QScrollView::AlwaysOn);
311   //ListEdit->setVScrollBarMode(QScrollView::AlwaysOff);
312   ListEdit->setFlow( QListView::LeftToRight );
313   ListEdit->setSelectionMode(QListWidget::ExtendedSelection);
314
315   AddElemButton = new QPushButton(GroupEdit);
316   AddElemButton->setIcon(IconAdd);
317   RemoveElemButton = new QPushButton(GroupEdit);
318   RemoveElemButton->setIcon(IconRemove);
319   SetFirstButton = new QPushButton(GroupEdit);
320   SetFirstButton->setIcon(IconFirst());
321
322   GroupEditLayout->addWidget(ListEdit,         0, 0, 2, 1);
323   GroupEditLayout->addWidget(AddElemButton,    0, 1);
324   GroupEditLayout->addWidget(RemoveElemButton, 0, 2);
325   GroupEditLayout->addWidget(SetFirstButton,   1, 1, 1, 2);
326
327   /***************************************************************/
328   GroupButtons = new QGroupBox(this);
329   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
330   GroupButtonsLayout->setSpacing(SPACING);
331   GroupButtonsLayout->setMargin(MARGIN);
332
333   buttonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons);
334   buttonOk->setAutoDefault(true);
335   buttonOk->setDefault(true);
336   buttonApply = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
337   buttonApply->setAutoDefault(true);
338   buttonCancel = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
339   buttonCancel->setAutoDefault(true);
340   buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
341   buttonHelp->setAutoDefault(true);
342
343   GroupButtonsLayout->addWidget(buttonOk);
344   GroupButtonsLayout->addSpacing(10);
345   GroupButtonsLayout->addWidget(buttonApply);
346   GroupButtonsLayout->addSpacing(10);
347   GroupButtonsLayout->addStretch();
348   GroupButtonsLayout->addWidget(buttonCancel);
349   GroupButtonsLayout->addWidget(buttonHelp);
350
351   /***************************************************************/
352   DlgLayout->addWidget(GroupConstructors);
353   DlgLayout->addWidget(GroupMesh);
354   DlgLayout->addWidget(TypeBox);
355   DlgLayout->addWidget(GroupCoincident);
356   DlgLayout->addWidget(GroupEdit);
357   DlgLayout->addWidget(GroupButtons);
358
359   GroupCoincidentWidget->setVisible( myAction != MERGE_NODES );
360   GroupCoincident      ->setVisible( myAction == MERGE_NODES );
361   //if GroupExclude->setVisible( myAction == MERGE_NODES );
362   GroupEdit->hide();
363
364   this->resize(10,10);
365
366   ShowIDs->setChecked( true );
367
368   Init(); // Initialisations
369 }
370
371 //=================================================================================
372 // function : ~SMESHGUI_MergeDlg()
373 // purpose  : Destroys the object and frees any allocated resources
374 //=================================================================================
375 SMESHGUI_MergeDlg::~SMESHGUI_MergeDlg()
376 {
377   delete myIdPreview;
378 }
379
380 //=================================================================================
381 // function : Init()
382 // purpose  :
383 //=================================================================================
384 void SMESHGUI_MergeDlg::Init()
385 {
386   if ( myAction == MERGE_NODES ) {
387     SpinBoxTolerance->RangeStepAndValidator(0.0, COORD_MAX, 0.00001, "len_tol_precision");
388     SpinBoxTolerance->SetValue(1e-05);
389   }
390
391   RadioButton->setChecked(true);
392
393   GroupType->button(0)->setChecked(true);
394
395   myEditCurrentArgument = (QWidget*)LineEditMesh;
396
397   myActor = 0;
398   mySubMeshOrGroup = SMESH::SMESH_subMesh::_nil();
399
400   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
401
402   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
403   myIsBusy = false;
404
405   /* signals and slots connections */
406   connect(buttonOk,     SIGNAL(clicked()), this, SLOT(ClickOnOk()));
407   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
408   connect(buttonApply,  SIGNAL(clicked()), this, SLOT(ClickOnApply()));
409   connect(buttonHelp,   SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
410
411   if ( KeepList )
412   {
413     connect(SelectKeepNodesButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument()));
414     connect(KeepFromButGroup, SIGNAL (buttonClicked(int)), SLOT(onKeepNodeSourceChanged(int)));
415     connect(AddKeepNodesButton, SIGNAL (clicked()), this, SLOT(onAddKeepNode()));
416     connect(RemoveKeepNodesButton, SIGNAL (clicked()), this, SLOT(onRemoveKeepNode()));
417     connect(KeepList, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectKeepNode()));
418   }
419   connect(SelectMeshButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument()));
420   connect(DetectButton, SIGNAL (clicked()), this, SLOT(onDetect()));
421   connect(ListCoincident, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectGroup()));
422   connect(AddGroupButton, SIGNAL (clicked()), this, SLOT(onAddGroup()));
423   connect(RemoveGroupButton, SIGNAL (clicked()), this, SLOT(onRemoveGroup()));
424   connect(SelectAllCB, SIGNAL(toggled(bool)), this, SLOT(onSelectAll(bool)));
425   connect(ShowIDs, SIGNAL(toggled(bool)), this, SLOT(onSelectGroup()));
426   connect(ListEdit, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectElementFromGroup()));
427   connect(AddElemButton, SIGNAL (clicked()), this, SLOT(onAddElement()));
428   connect(RemoveElemButton, SIGNAL (clicked()), this, SLOT(onRemoveElement()));
429   connect(SetFirstButton, SIGNAL( clicked() ), this, SLOT( onSetFirst()));
430   connect(GroupType, SIGNAL(buttonClicked(int)), this, SLOT(onTypeChanged(int)));
431
432   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
433   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
434   /* to close dialog if study change */
435   connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
436   connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this,  SLOT(onOpenView()));
437   connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
438   // Init Mesh field from selection
439   SelectionIntoArgument();
440
441   // Update Buttons
442   updateControls();
443   
444   if ( myAction == MERGE_NODES )
445     myHelpFileName = "merging_nodes_page.html";
446   else
447     myHelpFileName = "merging_elements_page.html";
448 }
449
450 //=================================================================================
451 // function : FindGravityCenter()
452 // purpose  :
453 //=================================================================================
454 void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap,
455                                           std::vector<int>&      theIDs,
456                                           std::list< gp_XYZ > &  theGrCentersXYZ)
457 {
458   if (!myActor)
459     return;
460
461   SMDS_Mesh* aMesh = 0;
462   aMesh = myActor->GetObject()->GetMesh();
463   if (!aMesh)
464     return;
465
466   int nbNodes;
467
468   theIDs.reserve( theElemsIdMap.Extent() );
469   TColStd_MapIteratorOfMapOfInteger idIter( theElemsIdMap );
470   for( ; idIter.More(); idIter.Next() ) {
471     const SMDS_MeshElement* anElem = aMesh->FindElement(idIter.Key());
472     if ( !anElem )
473       continue;
474     theIDs.push_back( idIter.Key() );
475
476     gp_XYZ anXYZ(0., 0., 0.);
477     SMDS_ElemIteratorPtr nodeIt = anElem->nodesIterator();
478     for ( nbNodes = 0; nodeIt->more(); nbNodes++ ) {
479       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
480       anXYZ.Add( gp_XYZ( node->X(), node->Y(), node->Z() ) );
481     }
482     anXYZ.Divide( nbNodes );
483     
484     theGrCentersXYZ.push_back( anXYZ );
485   }
486 }
487
488 //=================================================================================
489 // function : ClickOnApply()
490 // purpose  :
491 //=================================================================================
492 bool SMESHGUI_MergeDlg::ClickOnApply()
493 {
494   if (mySMESHGUI->isActiveStudyLocked() || myMesh->_is_nil())
495     return false;
496
497   try {
498     if (myTypeId == TYPE_AUTO)
499       onDetect();
500
501     SUIT_OverrideCursor aWaitCursor;
502     SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
503
504     SMESH::long_array_var anIds = new SMESH::long_array;
505     SMESH::array_of_long_array_var aGroupsOfElements = new SMESH::array_of_long_array;
506
507     if ( ListCoincident->count() == 0) {
508       if ( myAction == MERGE_NODES )
509         SUIT_MessageBox::warning(this,
510                                  tr("SMESH_WARNING"),
511                                  tr("SMESH_NO_NODES_DETECTED"));
512       else
513         SUIT_MessageBox::warning(this,
514                                  tr("SMESH_WARNING"),
515                                  tr("SMESH_NO_ELEMENTS_DETECTED"));
516       return false;
517     }
518
519     aGroupsOfElements->length(ListCoincident->count());
520
521     int anArrayNum = 0;
522     for (int i = 0; i < ListCoincident->count(); i++) {
523       QStringList aListIds = ListCoincident->item(i)->text().split(" ", QString::SkipEmptyParts);
524
525       anIds->length(aListIds.count());
526       for (int i = 0; i < aListIds.count(); i++)
527         anIds[i] = aListIds[i].toInt();
528
529       aGroupsOfElements[anArrayNum++] = anIds.inout();
530     }
531
532     SMESH::ListOfIDSources_var nodesToKeep;
533     SMESH::IDSource_wrap tmpIdSource;
534     if ( myAction == MERGE_NODES )
535     {
536       nodesToKeep = new SMESH::ListOfIDSources();
537       int i, nb = KeepList->count();
538       if ( isKeepNodesIDsSelection() )
539       {
540         SMESH::long_array_var anIdList = new SMESH::long_array();
541         anIdList->length(nb);
542         for (i = 0; i < nb; i++)
543           anIdList[i] = KeepList->item(i)->text().toInt();
544
545         if ( nb > 0 )
546         {
547           tmpIdSource = aMeshEditor->MakeIDSource( anIdList, SMESH::NODE );
548           nodesToKeep->length( 1 );
549           nodesToKeep[0] = SMESH::SMESH_IDSource::_duplicate( tmpIdSource.in() );
550         }
551       }
552       else
553       {
554         nodesToKeep->length( nb );
555         int nbObj = 0;
556         for (i = 0; i < nb; i++)
557         {
558           QString entry = KeepList->item( i )->data( Qt::UserRole ).toString();
559           Handle(SALOME_InteractiveObject) anIO =
560             new SALOME_InteractiveObject( entry.toStdString().c_str(), "SMESH" );
561           SMESH::SMESH_IDSource_var idSrc =
562             SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( anIO );
563           if ( !idSrc->_is_nil() )
564             nodesToKeep[ nbObj++ ] = SMESH::SMESH_IDSource::_duplicate( idSrc );
565         }
566         nodesToKeep->length( nbObj );
567       }
568       KeepList->clear();
569     }
570
571     if( myAction == MERGE_NODES )
572       aMeshEditor->MergeNodes (aGroupsOfElements.inout(), nodesToKeep);
573     else
574       aMeshEditor->MergeElements (aGroupsOfElements.inout());
575
576     if ( myTypeId == TYPE_AUTO ) {
577       if (myAction == MERGE_NODES )
578         SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"),
579                                      tr("SMESH_MERGED_NODES").arg(QString::number(ListCoincident->count()).toLatin1().data()));
580       else
581         SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"),
582                                      tr("SMESH_MERGED_ELEMENTS").arg(QString::number(ListCoincident->count()).toLatin1().data()));
583     }
584     nodesToKeep->length(0); // release before tmpIdSource calls UnRegister()
585
586   }
587   catch(...) {
588   }
589
590   ListCoincident->clear();
591
592   myEditCurrentArgument = (QWidget*)LineEditMesh;
593
594   SMESH::UpdateView();
595   SMESHGUI::Modified();
596
597   return true;
598 }
599
600 //=================================================================================
601 // function : ClickOnOk()
602 // purpose  :
603 //=================================================================================
604 void SMESHGUI_MergeDlg::ClickOnOk()
605 {
606   if (ClickOnApply())
607     reject();
608 }
609
610 //=================================================================================
611 // function : reject()
612 // purpose  :
613 //=================================================================================
614 void SMESHGUI_MergeDlg::reject()
615 {
616   myIdPreview->SetPointsLabeled(false);
617   SMESH::SetPointRepresentation(false);
618   disconnect(mySelectionMgr, 0, this, 0);
619   disconnect(mySMESHGUI, 0, this, 0);
620   mySMESHGUI->ResetState();
621
622   mySelectionMgr->clearFilters();
623   //mySelectionMgr->clearSelected();
624
625   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
626     aViewWindow->SetSelectionMode(ActorSelection);
627
628   QDialog::reject();
629 }
630
631 //=================================================================================
632 // function : onOpenView()
633 // purpose  :
634 //=================================================================================
635 void SMESHGUI_MergeDlg::onOpenView()
636 {
637   if ( mySelector ) {
638     SMESH::SetPointRepresentation(false);
639   }
640   else {
641     mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
642     ActivateThisDialog();
643   }
644 }
645
646 //=================================================================================
647 // function : onCloseView()
648 // purpose  :
649 //=================================================================================
650 void SMESHGUI_MergeDlg::onCloseView()
651 {
652   DeactivateActiveDialog();
653   mySelector = 0;
654 }
655
656 //=================================================================================
657 // function : ClickOnHelp()
658 // purpose  :
659 //=================================================================================
660 void SMESHGUI_MergeDlg::ClickOnHelp()
661 {
662   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
663   if (app) 
664     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
665   else {
666     QString platform;
667 #ifdef WIN32
668     platform = "winapplication";
669 #else
670     platform = "application";
671 #endif
672     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
673                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
674                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
675                                                                  platform)).
676                              arg(myHelpFileName));
677   }
678 }
679
680 //=================================================================================
681 // function : onEditGroup()
682 // purpose  :
683 //=================================================================================
684 void SMESHGUI_MergeDlg::onEditGroup()
685 {
686   QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
687   if ( selItems.count() != 1 ) {
688     ListEdit->clear();
689     return;
690   }
691
692   QStringList aNewIds;
693
694   for (int i = 0; i < ListEdit->count(); i++ )
695     aNewIds.append(ListEdit->item(i)->text());
696
697   ListCoincident->clearSelection();
698   selItems.first()->setText(aNewIds.join(" "));
699   selItems.first()->setSelected(true);
700 }
701
702 //=================================================================================
703 // function : updateControls()
704 // purpose  :
705 //=================================================================================
706 void SMESHGUI_MergeDlg::updateControls()
707 {
708   if (ListEdit->count() == 0)
709     SetFirstButton->setEnabled(false);
710
711   bool groupsEmpty = ( myTypeId != TYPE_AUTO );
712   for (int i = 0; i < ListCoincident->count() && groupsEmpty; i++) {
713     QStringList aListIds = ListCoincident->item(i)->text().split(" ", QString::SkipEmptyParts);
714     groupsEmpty = ( aListIds.count() < 2 );
715   }
716   bool enable = ( !myMesh->_is_nil() && !groupsEmpty );
717   buttonOk->setEnabled(enable);
718   buttonApply->setEnabled(enable);
719   DetectButton->setEnabled( !myMesh->_is_nil() );
720
721   if ( myAction == MERGE_NODES )
722   {
723     bool has2ndOrder = (( !myMesh->_is_nil() ) &&
724                         ( myMesh->NbEdgesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 ||
725                           myMesh->NbFacesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 ||
726                           myMesh->NbVolumesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 ));
727
728     SeparateCornersAndMedium->setEnabled( has2ndOrder );
729
730     if ( myEditCurrentArgument != KeepList )
731     {
732       AddKeepNodesButton->setEnabled( false );
733       RemoveKeepNodesButton->setEnabled( false );
734       KeepList->clearSelection();
735     }
736   }
737 }
738
739 //=================================================================================
740 // function : onDetect()
741 // purpose  :
742 //=================================================================================
743 void SMESHGUI_MergeDlg::onDetect()
744 {
745   if ( myMesh->_is_nil() || LineEditMesh->text().isEmpty() )
746     return;
747
748   try {
749     SUIT_OverrideCursor aWaitCursor;
750     SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
751
752     ListCoincident->clear();
753     ListEdit->clear();
754
755     SMESH::array_of_long_array_var aGroupsArray;
756     SMESH::ListOfIDSources_var aExcludeGroups = new SMESH::ListOfIDSources;
757
758     SMESH::SMESH_IDSource_var src;
759     if ( mySubMeshOrGroup->_is_nil() ) src = SMESH::SMESH_IDSource::_duplicate( myMesh );
760     else                               src = SMESH::SMESH_IDSource::_duplicate( mySubMeshOrGroup );
761
762     switch (myAction) {
763     case MERGE_NODES :
764       for ( int i = 0; GroupExclude->isChecked() && i < ListExclude->count(); i++ ) {
765         if ( ListExclude->item( i )->checkState() == Qt::Checked ) {
766           aExcludeGroups->length( aExcludeGroups->length()+1 );
767           aExcludeGroups[ aExcludeGroups->length()-1 ] = SMESH::SMESH_IDSource::_duplicate( myGroups[i] );
768         }
769       }
770       aMeshEditor->FindCoincidentNodesOnPartBut(src.in(),
771                                                 SpinBoxTolerance->GetValue(), 
772                                                 aGroupsArray.out(),
773                                                 aExcludeGroups.in(),
774                                                 SeparateCornersAndMedium->isEnabled() &&
775                                                 SeparateCornersAndMedium->isChecked());
776       break;
777     case MERGE_ELEMENTS :
778       aMeshEditor->FindEqualElements(src.in(), aGroupsArray.out());
779       break;
780     }
781     
782     for (int i = 0; i < aGroupsArray->length(); i++) {
783       SMESH::long_array& aGroup = aGroupsArray[i];
784
785       QStringList anIDs;
786       for (int j = 0; j < aGroup.length(); j++)
787         anIDs.append(QString::number(aGroup[j]));
788
789       ListCoincident->addItem(anIDs.join(" "));
790     }
791   } catch(...) {
792   }
793
794   ListCoincident->selectAll();
795   updateControls();
796   SMESH::UpdateView();
797 }
798
799 //=================================================================================
800 // function : onSelectGroup()
801 // purpose  :
802 //=================================================================================
803 void SMESHGUI_MergeDlg::onSelectGroup()
804 {
805   if (myIsBusy || !myActor)
806     return;
807
808   if( ListCoincident->count() != ListCoincident->selectedItems().count() )
809     SelectAllCB->setChecked( false );
810
811   myEditCurrentArgument = (QWidget*)ListCoincident;
812
813   myIsBusy = true;
814   ListEdit->clear();
815
816   TColStd_MapOfInteger anIndices;
817   QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
818   QListWidgetItem* anItem;
819   QStringList aListIds;
820
821   ListEdit->clear();
822
823   foreach(anItem, selItems) {
824     aListIds = anItem->text().split(" ", QString::SkipEmptyParts);
825     for (int i = 0; i < aListIds.count(); i++)
826       anIndices.Add(aListIds[i].toInt());
827   }
828
829   if (selItems.count() == 1) {
830     ListEdit->addItems(aListIds);
831     ListEdit->selectAll();
832   }
833
834   mySelector->AddOrRemoveIndex(myActor->getIO(), anIndices, false);
835   SALOME_ListIO aList;
836   aList.Append(myActor->getIO());
837   mySelectionMgr->setSelectedObjects(aList,false);
838   
839   if (ShowIDs->isChecked()) 
840     if ( myAction == MERGE_NODES ) {
841       myIdPreview->SetPointsData(myActor->GetObject()->GetMesh(), anIndices);
842       myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
843     }
844     else {
845       std::list< gp_XYZ > aGrCentersXYZ;
846       std::vector<int>    anIDs;
847       FindGravityCenter(anIndices, anIDs, aGrCentersXYZ);
848       myIdPreview->SetElemsData( anIDs, aGrCentersXYZ );
849       myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
850     }
851   else
852     myIdPreview->SetPointsLabeled(false);
853
854   updateControls();
855   myIsBusy = false;
856 }
857
858 //=================================================================================
859 // function : onSelectAll()
860 // purpose  :
861 //=================================================================================
862 void SMESHGUI_MergeDlg::onSelectAll (bool isToggled)
863 {
864   if ( isToggled )
865     ListCoincident->selectAll();
866   else
867     ListCoincident->clearSelection();
868 }
869
870 //=================================================================================
871 // function : onSelectElementFromGroup()
872 // purpose  :
873 //=================================================================================
874 void SMESHGUI_MergeDlg::onSelectElementFromGroup()
875 {
876   if (myIsBusy || !myActor)
877     return;
878
879   TColStd_MapOfInteger anIndices;
880   QList<QListWidgetItem*> selItems = ListEdit->selectedItems();
881   QListWidgetItem* anItem;
882
883   foreach(anItem, selItems)
884     anIndices.Add(anItem->text().toInt());
885
886   SetFirstButton->setEnabled(selItems.count() == 1);
887
888   mySelector->AddOrRemoveIndex(myActor->getIO(), anIndices, false);
889   SALOME_ListIO aList;
890   aList.Append(myActor->getIO());
891   mySelectionMgr->setSelectedObjects(aList);
892   
893   if (ShowIDs->isChecked())
894     if (myAction == MERGE_NODES) {
895       myIdPreview->SetPointsData(myActor->GetObject()->GetMesh(), anIndices);
896       myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
897     }
898     else {
899       std::list< gp_XYZ > aGrCentersXYZ;
900       std::vector<int>    anIDs;
901       FindGravityCenter(anIndices, anIDs, aGrCentersXYZ);
902       myIdPreview->SetElemsData(anIDs, aGrCentersXYZ);
903       myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
904     }
905   else 
906     myIdPreview->SetPointsLabeled(false);
907 }
908
909 //=================================================================================
910 // function : onAddGroup()
911 // purpose  :
912 //=================================================================================
913 void SMESHGUI_MergeDlg::onAddGroup()
914 {
915   if ( myMesh->_is_nil() || LineEditMesh->text().isEmpty() )
916     return;
917
918   QString anIDs = "";
919   int aNbElements = 0;
920   aNbElements = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), anIDs);
921
922   if (aNbElements < 1)
923     return;
924   
925   ListCoincident->clearSelection();
926   ListCoincident->addItem(anIDs);
927   int nbGroups = ListCoincident->count();
928   if (nbGroups) {
929     ListCoincident->setCurrentRow(nbGroups-1);
930     ListCoincident->item(nbGroups-1)->setSelected(true);
931   }
932   else {
933     // VSR ? this code seems to be never executed!!!
934     ListCoincident->setCurrentRow(0);
935     //ListCoincident->setSelected(0, true); // VSR: no items - no selection
936   }
937
938   updateControls();
939 }
940
941 //=================================================================================
942 // function : onRemoveGroup()
943 // purpose  :
944 //=================================================================================
945 void SMESHGUI_MergeDlg::onRemoveGroup()
946 {
947   if (myEditCurrentArgument != (QWidget*)ListCoincident)
948     return;
949   myIsBusy = true;
950
951   QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
952   QListWidgetItem* anItem;
953
954   foreach(anItem, selItems)
955     delete anItem;
956
957   ListEdit->clear();
958   myIdPreview->SetPointsLabeled(false);
959   updateControls();
960   SMESH::UpdateView();
961   myIsBusy = false;
962
963   if( ListCoincident->count() == 0 ) {
964     myEditCurrentArgument = (QWidget*)LineEditMesh;
965     SelectAllCB->setChecked( false );
966   }
967 }
968
969 //=================================================================================
970 // function : onAddElement()
971 // purpose  :
972 //=================================================================================
973 void SMESHGUI_MergeDlg::onAddElement()
974 {
975   if (!myActor)
976     return;
977   myIsBusy = true;
978
979   QString aListStr = "";
980   int aNbNnodes = 0;
981
982   aNbNnodes = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), aListStr);
983   if (aNbNnodes < 1)
984     return;
985
986   QStringList aNodes = aListStr.split(" ", QString::SkipEmptyParts);
987
988   for (QStringList::iterator it = aNodes.begin(); it != aNodes.end(); ++it) {
989     QList<QListWidgetItem*> found = ListEdit->findItems(*it, Qt::MatchExactly);
990     if ( found.count() == 0 ) {
991       QListWidgetItem* anItem = new QListWidgetItem(*it);
992       ListEdit->addItem(anItem);
993       anItem->setSelected(true);
994     }
995     else {
996       QListWidgetItem* anItem;
997       foreach(anItem, found) anItem->setSelected(true);
998     }
999   }
1000
1001   myIsBusy = false;
1002   onEditGroup();
1003 }
1004
1005 //=================================================================================
1006 // function : onRemoveElement()
1007 // purpose  :
1008 //=================================================================================
1009 void SMESHGUI_MergeDlg::onRemoveElement()
1010 {
1011   if (myEditCurrentArgument != (QWidget*)ListCoincident)
1012     return;
1013   myIsBusy = true;
1014
1015   QList<QListWidgetItem*> selItems = ListEdit->selectedItems();
1016   QListWidgetItem* anItem;
1017
1018   foreach(anItem, selItems)
1019     delete anItem;
1020   
1021   myIsBusy = false;
1022   onEditGroup();
1023
1024   if( ListCoincident->count() == 0 ) {
1025     myEditCurrentArgument = (QWidget*)LineEditMesh;
1026     SelectAllCB->setChecked( false );
1027   }
1028 }
1029
1030 //=================================================================================
1031 // function : onSetFirst()
1032 // purpose  :
1033 //=================================================================================
1034 void SMESHGUI_MergeDlg::onSetFirst()
1035 {
1036   if (myEditCurrentArgument != (QWidget*)ListCoincident)
1037     return;
1038   myIsBusy = true;
1039   
1040   QList<QListWidgetItem*> selItems = ListEdit->selectedItems();
1041   QListWidgetItem* anItem;
1042   
1043   foreach(anItem, selItems) {
1044     ListEdit->takeItem(ListEdit->row(anItem));
1045     ListEdit->insertItem(0, anItem);
1046   }
1047
1048   myIsBusy = false;
1049   onEditGroup();
1050 }
1051
1052 //=================================================================================
1053 // function : SetEditCurrentArgument()
1054 // purpose  :
1055 //=================================================================================
1056 void SMESHGUI_MergeDlg::SetEditCurrentArgument()
1057 {
1058   QPushButton* send = (QPushButton*)sender();
1059
1060   disconnect(mySelectionMgr, 0, this, 0);
1061   mySelectionMgr->clearSelected();
1062   mySelectionMgr->clearFilters();
1063
1064   if (send == SelectMeshButton)
1065   {
1066     myEditCurrentArgument = (QWidget*)LineEditMesh;
1067     SMESH::SetPointRepresentation(false);
1068     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1069       aViewWindow->SetSelectionMode(ActorSelection);
1070     if (myTypeId == TYPE_MANUAL)
1071       mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter);
1072   }
1073   else if ( send == SelectKeepNodesButton && send )
1074   {
1075     myEditCurrentArgument = (QWidget*)KeepList;
1076     KeepList->setWrapping( isKeepNodesIDsSelection() );
1077     if ( isKeepNodesIDsSelection() )
1078     {
1079       SMESH::SetPointRepresentation( true );
1080       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1081         aViewWindow->SetSelectionMode( NodeSelection );
1082     }
1083     else
1084     {
1085       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1086         aViewWindow->SetSelectionMode( ActorSelection );
1087       mySelectionMgr->installFilter( mySubMeshOrGroupFilter );
1088     }
1089   }
1090
1091   myEditCurrentArgument->setFocus();
1092   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
1093   SelectionIntoArgument();
1094 }
1095
1096 //=================================================================================
1097 // function : SelectionIntoArgument()
1098 // purpose  : Called when selection has changed or other case
1099 //=================================================================================
1100 void SMESHGUI_MergeDlg::SelectionIntoArgument()
1101 {
1102   if (myEditCurrentArgument == (QWidget*)LineEditMesh)
1103   {
1104     QString aString = "";
1105     LineEditMesh->setText(aString);
1106
1107     ListCoincident->clear();
1108     ListEdit->clear();
1109     myActor = 0;
1110     myMesh = SMESH::SMESH_Mesh::_nil();
1111     QString aCurrentEntry = myEntry;
1112
1113     int nbSel = SMESH::GetNameOfSelectedIObjects(mySelectionMgr, aString);
1114     if (nbSel != 1) {
1115       myIdPreview->SetPointsLabeled(false);
1116       SMESH::SetPointRepresentation(false);
1117       mySelectionMgr->clearFilters();
1118       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1119         aViewWindow->SetSelectionMode(ActorSelection);
1120       return;
1121     }
1122
1123     SALOME_ListIO aList;
1124     mySelectionMgr->selectedObjects(aList);
1125
1126     Handle(SALOME_InteractiveObject) IO = aList.First();
1127     myEntry = IO->getEntry();
1128     myMesh = SMESH::GetMeshByIO(IO);
1129
1130     if ( myEntry != aCurrentEntry && KeepList )
1131       KeepList->clear();
1132
1133     if (myMesh->_is_nil())
1134       return;
1135
1136     LineEditMesh->setText(aString);
1137
1138     myActor = SMESH::FindActorByEntry(IO->getEntry());
1139     if (!myActor)
1140       myActor = SMESH::FindActorByObject(myMesh);
1141
1142     if ( myActor && myTypeId == TYPE_MANUAL && mySelector->IsSelectionEnabled() ) {
1143       mySubMeshOrGroup = SMESH::SMESH_IDSource::_nil();
1144       mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter);
1145
1146       if ((!SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(IO)->_is_nil() || //SUBMESH OR GROUP
1147            !SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(IO)->_is_nil()) &&
1148           !SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(IO)->_is_nil())
1149         mySubMeshOrGroup = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(IO);
1150
1151       if (myAction == MERGE_NODES) {
1152         SMESH::SetPointRepresentation(true);
1153         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1154           aViewWindow->SetSelectionMode(NodeSelection);
1155       }
1156       else
1157         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1158           aViewWindow->SetSelectionMode(CellSelection);
1159     }
1160
1161     // process groups
1162     if ( myAction == MERGE_NODES && !myMesh->_is_nil() && myEntry != aCurrentEntry ) {
1163       myGroups.clear();
1164       ListExclude->clear();
1165       SMESH::ListOfGroups_var aListOfGroups = myMesh->GetGroups();
1166       for( int i = 0, n = aListOfGroups->length(); i < n; i++ ) {
1167         SMESH::SMESH_GroupBase_var aGroup = aListOfGroups[i];
1168         if ( !aGroup->_is_nil() ) { // && aGroup->GetType() == SMESH::NODE
1169           QString aGroupName( aGroup->GetName() );
1170           if ( !aGroupName.isEmpty() ) {
1171             myGroups.append(SMESH::SMESH_GroupBase::_duplicate(aGroup));
1172             QListWidgetItem* item = new QListWidgetItem( aGroupName );
1173             item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
1174             item->setCheckState( Qt::Unchecked );
1175             ListExclude->addItem( item );
1176           }
1177         }
1178       }
1179     }
1180
1181     updateControls();
1182   }
1183
1184   else if (myEditCurrentArgument == (QWidget*)KeepList && KeepList)
1185   {
1186     AddKeepNodesButton->setEnabled( false );
1187     RemoveKeepNodesButton->setEnabled( false );
1188     if ( isKeepNodesIDsSelection() )
1189     {
1190       if (!myMesh->_is_nil() && !myActor)
1191         myActor = SMESH::FindActorByObject(myMesh);
1192
1193       if ( mySelector && myActor )
1194       {
1195         KeepList->clearSelection();
1196         QString anIDs = "";
1197         int aNbNodes = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), anIDs);
1198         if (aNbNodes > 0)
1199         {
1200           QStringList anNodes = anIDs.split( " ", QString::SkipEmptyParts);
1201           QList<QListWidgetItem*> listItemsToSel;
1202           QListWidgetItem* anItem;
1203           int nbFound = 0;
1204           for (QStringList::iterator it = anNodes.begin(); it != anNodes.end(); ++it)
1205           {
1206             QList<QListWidgetItem*> found = KeepList->findItems(*it, Qt::MatchExactly);
1207             foreach(anItem, found)
1208               if (!anItem->isSelected())
1209                 listItemsToSel.push_back(anItem);
1210             nbFound += found.count();
1211           }
1212           bool blocked = KeepList->signalsBlocked();
1213           KeepList->blockSignals(true);
1214           foreach(anItem, listItemsToSel) anItem->setSelected(true);
1215           KeepList->blockSignals(blocked);
1216           //onSelectKeepNode();
1217           AddKeepNodesButton->setEnabled( nbFound < aNbNodes );
1218           RemoveKeepNodesButton->setEnabled( nbFound > 0 );
1219         }
1220       }
1221     }
1222     else if ( !myMesh->_is_nil() )
1223     {
1224       SALOME_ListIO aList;
1225       mySelectionMgr->selectedObjects(aList);
1226       bool hasNewSelected = false;
1227       SALOME_ListIteratorOfListIO anIt (aList);
1228       for ( ; anIt.More() && !hasNewSelected; anIt.Next())
1229         if ( anIt.Value()->hasEntry() )
1230           hasNewSelected = isNewKeepNodesGroup( anIt.Value()->getEntry() );
1231
1232       AddKeepNodesButton->setEnabled( hasNewSelected );
1233       //RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() );
1234     }
1235   }
1236 }
1237
1238 //=================================================================================
1239 // function : DeactivateActiveDialog()
1240 // purpose  :
1241 //=================================================================================
1242 void SMESHGUI_MergeDlg::DeactivateActiveDialog()
1243 {
1244   if (GroupConstructors->isEnabled()) {
1245     GroupConstructors->setEnabled(false);
1246     TypeBox->setEnabled(false);
1247     GroupMesh->setEnabled(false);
1248     GroupCoincident->setEnabled(false);
1249     GroupEdit->setEnabled(false);
1250     GroupButtons->setEnabled(false);
1251     mySMESHGUI->ResetState();
1252     mySMESHGUI->SetActiveDialogBox(0);
1253   }
1254
1255   mySelectionMgr->clearSelected();
1256   disconnect(mySelectionMgr, 0, this, 0);
1257 }
1258
1259 //=================================================================================
1260 // function : ActivateThisDialog()
1261 // purpose  :
1262 //=================================================================================
1263 void SMESHGUI_MergeDlg::ActivateThisDialog()
1264 {
1265   /* Emit a signal to deactivate the active dialog */
1266   mySMESHGUI->EmitSignalDeactivateDialog();
1267   GroupConstructors->setEnabled(true);
1268   TypeBox->setEnabled(true);
1269   GroupMesh->setEnabled(true);
1270   GroupCoincident->setEnabled(true);
1271   GroupEdit->setEnabled(true);
1272   GroupButtons->setEnabled(true);
1273
1274   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
1275   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
1276   SelectionIntoArgument();
1277 }
1278
1279 //=================================================================================
1280 // function : enterEvent()
1281 // purpose  :
1282 //=================================================================================
1283 void SMESHGUI_MergeDlg::enterEvent (QEvent*)
1284 {
1285   if ( !GroupConstructors->isEnabled() ) {
1286     SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
1287     if ( aViewWindow && !mySelector) {
1288       mySelector = aViewWindow->GetSelector();
1289     }
1290     ActivateThisDialog();
1291   }
1292 }
1293
1294 //=================================================================================
1295 // function : keyPressEvent()
1296 // purpose  :
1297 //=================================================================================
1298 void SMESHGUI_MergeDlg::keyPressEvent( QKeyEvent* e)
1299 {
1300   QDialog::keyPressEvent( e );
1301   if ( e->isAccepted() )
1302     return;
1303
1304   if ( e->key() == Qt::Key_F1 ) {
1305     e->accept();
1306     ClickOnHelp();
1307   }
1308 }
1309
1310 //=================================================================================
1311 // function : onTypeChanged()
1312 // purpose  : the type radio button management
1313 //=================================================================================
1314 void SMESHGUI_MergeDlg::onTypeChanged (int id)
1315 {
1316   if (myTypeId == id)
1317     return;
1318
1319   myTypeId = id;
1320   switch (id)
1321   {
1322   case TYPE_AUTO: // automatic
1323
1324     myIdPreview->SetPointsLabeled(false);
1325     SMESH::SetPointRepresentation(false);
1326     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1327       aViewWindow->SetSelectionMode(ActorSelection);
1328     mySelectionMgr->clearFilters();
1329     if (myAction == MERGE_NODES)
1330       GroupCoincidentWidget->hide();
1331     else
1332       GroupCoincident->hide();
1333     GroupEdit->hide();
1334     break;
1335
1336   case TYPE_MANUAL: // manual
1337
1338     SMESH::UpdateView();
1339
1340     // Costruction of the logical filter
1341     SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter (SMESH::MESHorSUBMESH);
1342     SMESH_TypeFilter* aSmeshGroupFilter    = new SMESH_TypeFilter (SMESH::GROUP);
1343     
1344     QList<SUIT_SelectionFilter*> aListOfFilters;
1345     if (aMeshOrSubMeshFilter) aListOfFilters.append(aMeshOrSubMeshFilter);
1346     if (aSmeshGroupFilter)    aListOfFilters.append(aSmeshGroupFilter);
1347     
1348     myMeshOrSubMeshOrGroupFilter =
1349       new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR);
1350
1351     if (myAction == MERGE_NODES) {
1352       GroupCoincidentWidget->show();
1353       SMESH::SetPointRepresentation(true);
1354       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1355         if( mySelector->IsSelectionEnabled() )
1356           aViewWindow->SetSelectionMode(NodeSelection);
1357     }
1358     else {
1359       GroupCoincident->show();
1360       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1361         if( mySelector->IsSelectionEnabled() )
1362           aViewWindow->SetSelectionMode(CellSelection);
1363     }
1364     GroupEdit->show();
1365     break;
1366   }
1367   updateControls();
1368
1369   qApp->processEvents();
1370   updateGeometry();
1371   resize(10,10);
1372
1373   SelectionIntoArgument();
1374 }
1375
1376 //=======================================================================
1377 //function : isKeepNodesIDsSelection
1378 //purpose  : Return true of Nodes to keep are selected by IDs
1379 //=======================================================================
1380
1381 bool SMESHGUI_MergeDlg::isKeepNodesIDsSelection()
1382 {
1383   return KeepFromButGroup && KeepFromButGroup->checkedId() == 0;
1384 }
1385
1386 //=======================================================================
1387 //function : isNewKeepNodesGroup
1388 //purpose  : Return true if an object with given entry is NOT present in KeepList
1389 //=======================================================================
1390
1391 bool SMESHGUI_MergeDlg::isNewKeepNodesGroup( const char* entry )
1392 {
1393   if ( !entry || isKeepNodesIDsSelection() )
1394     return false;
1395
1396   for ( int i = 0; i < KeepList->count(); i++ )
1397     if ( KeepList->item( i )->data( Qt::UserRole ).toString() == entry )
1398       return false;
1399
1400   return true;
1401 }
1402
1403 //=======================================================================
1404 //function : onAddKeepNode
1405 //purpose  : SLOT called when [Add] of Nodes To Keep group is pressed
1406 //=======================================================================
1407
1408 void SMESHGUI_MergeDlg::onAddKeepNode()
1409 {
1410   if ( myIsBusy )
1411     return;
1412   myIsBusy = true;
1413
1414   if ( isKeepNodesIDsSelection() )
1415   {
1416     //KeepList->clearSelection();
1417     QString anIDs = "";
1418     int aNbNodes = 0;
1419     if ( myActor )
1420       aNbNodes = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), anIDs);
1421     if (aNbNodes > 0)
1422     {
1423       QStringList anNodes = anIDs.split( " ", QString::SkipEmptyParts);
1424       QList<QListWidgetItem*> listItemsToSel;
1425       QListWidgetItem* anItem;
1426       for (QStringList::iterator it = anNodes.begin(); it != anNodes.end(); ++it)
1427       {
1428         QList<QListWidgetItem*> found = KeepList->findItems(*it, Qt::MatchExactly);
1429         if (found.count() == 0) {
1430           anItem = new QListWidgetItem(*it);
1431           KeepList->addItem(anItem);
1432           if (!anItem->isSelected())
1433             listItemsToSel.push_back(anItem);
1434         }
1435         else {
1436           foreach(anItem, found)
1437             if (!anItem->isSelected())
1438               listItemsToSel.push_back(anItem);
1439         }
1440       }
1441       bool blocked = KeepList->signalsBlocked();
1442       KeepList->blockSignals(true);
1443       foreach(anItem, listItemsToSel) anItem->setSelected(true);
1444       KeepList->blockSignals(blocked);
1445       //onSelectKeepNode();
1446     }
1447     RemoveKeepNodesButton->setEnabled( aNbNodes > 0 );
1448   }
1449   else
1450   {
1451     SALOME_ListIO aList;
1452     mySelectionMgr->selectedObjects(aList);
1453     SALOME_ListIteratorOfListIO anIt (aList);
1454     for ( ; anIt.More(); anIt.Next()) {
1455       Handle(SALOME_InteractiveObject) anIO = anIt.Value();
1456       if ( isNewKeepNodesGroup( anIO->getEntry() ))
1457       {
1458         QListWidgetItem* anItem = new QListWidgetItem( anIO->getName() );
1459         anItem->setData( Qt::UserRole, QString( anIO->getEntry() ));
1460         KeepList->addItem(anItem);
1461       }
1462     }
1463     //RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() );
1464   }
1465
1466   AddKeepNodesButton->setEnabled( false );
1467
1468   myIsBusy = false;
1469 }
1470
1471 //=======================================================================
1472 //function : onRemoveKeepNode
1473 //purpose  : SLOT called when [Remove] of Nodes To Keep group is pressed
1474 //=======================================================================
1475
1476 void SMESHGUI_MergeDlg::onRemoveKeepNode()
1477 {
1478   // if ( isKeepNodesIDsSelection() )
1479   // {
1480   // }
1481   // else
1482   {
1483     QList<QListWidgetItem*> selItems = KeepList->selectedItems();
1484     QListWidgetItem* item;
1485     foreach(item, selItems) delete item;
1486   }
1487   if ( isKeepNodesIDsSelection() )
1488   {
1489     AddKeepNodesButton->setEnabled( false );
1490   }
1491   RemoveKeepNodesButton->setEnabled( false );
1492 }
1493
1494 //=======================================================================
1495 //function : onSelectKeepNode
1496 //purpose  : SLOT called when selection in KeepList changes
1497 //=======================================================================
1498
1499 void SMESHGUI_MergeDlg::onSelectKeepNode()
1500 {
1501   if ( myIsBusy || !isEnabled() ) return;
1502   myIsBusy = true;
1503
1504   if ( isKeepNodesIDsSelection() )
1505   {
1506     if ( myActor )
1507     {
1508       mySelectionMgr->clearSelected();
1509       TColStd_MapOfInteger aIndexes;
1510       QList<QListWidgetItem*> selItems = KeepList->selectedItems();
1511       QListWidgetItem* anItem;
1512       foreach(anItem, selItems) aIndexes.Add(anItem->text().toInt());
1513       mySelector->AddOrRemoveIndex(myActor->getIO(), aIndexes, false);
1514       SALOME_ListIO aList;
1515       aList.Append(myActor->getIO());
1516       mySelectionMgr->setSelectedObjects(aList,false);
1517
1518       AddKeepNodesButton->setEnabled( false );
1519       RemoveKeepNodesButton->setEnabled( aIndexes.Extent() > 0 );
1520     }
1521   }
1522   else
1523   {
1524     RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() );
1525   }
1526   myIsBusy = false;
1527 }
1528
1529 //=======================================================================
1530 //function : onKeepNodeSourceChanged
1531 //purpose  : SLOT called when type of source of Nodes To Keep change from
1532 //           IDs to groups or vice versa
1533 //=======================================================================
1534
1535 void SMESHGUI_MergeDlg::onKeepNodeSourceChanged(int isGroup)
1536 {
1537   KeepList->clear();
1538   SelectKeepNodesButton->click();
1539 }