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