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