Salome HOME
Merge branch 'V8_4_BR'
[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     AvoidMakingHoles = new QCheckBox(tr("AVOID_MAKING_HOLES"), NodeSpecWidget );
195     AvoidMakingHoles->setChecked( false );
196
197     QGridLayout* NodeSpecLayout = new QGridLayout(NodeSpecWidget);
198     NodeSpecLayout->setSpacing(SPACING);
199     NodeSpecLayout->setMargin(0);
200
201     NodeSpecLayout->addWidget(TextLabelTolerance,       0, 0 );
202     NodeSpecLayout->addWidget(SpinBoxTolerance,         0, 1 );
203     NodeSpecLayout->addWidget(SeparateCornersAndMedium, 1, 0, 1, 2 );
204     NodeSpecLayout->addWidget(AvoidMakingHoles,         2, 0, 1, 2 );
205
206     /***************************************************************/
207     // Exclude groups
208
209     GroupExclude = new QGroupBox(tr("EXCLUDE_GROUPS"), this );
210     GroupExclude->setCheckable( true );
211     GroupExclude->setChecked( false );
212     ListExclude = new QListWidget( GroupExclude );
213     QVBoxLayout* GroupExcludeLayout = new QVBoxLayout(GroupExclude);
214     GroupExcludeLayout->setSpacing(SPACING);
215     GroupExcludeLayout->setMargin(MARGIN);
216     GroupExcludeLayout->addWidget(ListExclude);
217
218     /***************************************************************/
219     // Nodes to keep
220
221     GroupKeep = new QGroupBox(tr("KEEP_NODES"), this);
222     SelectKeepNodesButton = new QPushButton( GroupKeep );
223     SelectKeepNodesButton->setIcon( IconSelect );
224     QLabel*       selectLabel = new QLabel(tr("SELECT"));
225     QRadioButton*   idsButton = new QRadioButton(tr("SMESH_NODES"), GroupKeep);
226     QRadioButton* groupButton = new QRadioButton(tr("GROUP_SUBMESH"), GroupKeep);
227     KeepFromButGroup = new QButtonGroup( this );
228     KeepFromButGroup->addButton( idsButton,   0 );
229     KeepFromButGroup->addButton( groupButton, 1 );
230     groupButton->setChecked( true );
231     KeepList = new QListWidget( GroupKeep );
232     KeepList->setSelectionMode(QAbstractItemView::ExtendedSelection);
233     KeepList->setFlow(QListView::TopToBottom);
234     AddKeepNodesButton    = new QPushButton(tr("SMESH_BUT_ADD"), GroupKeep );
235     RemoveKeepNodesButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupKeep );
236     QGridLayout* GroupKeepLayout = new QGridLayout(GroupKeep);
237     GroupKeepLayout->setSpacing( SPACING );
238     GroupKeepLayout->setMargin ( MARGIN );
239     GroupKeepLayout->addWidget( SelectKeepNodesButton, 0, 0 );
240     GroupKeepLayout->addWidget( selectLabel,           0, 1 );
241     GroupKeepLayout->addWidget( idsButton,             0, 2 );
242     GroupKeepLayout->addWidget( groupButton,           0, 3, 1, 2 );
243     GroupKeepLayout->addWidget( KeepList,              1, 0, 3, 4 );
244     GroupKeepLayout->addWidget( AddKeepNodesButton,    1, 4, 1, 1 );
245     GroupKeepLayout->addWidget( RemoveKeepNodesButton, 2, 4, 1, 1 );
246     GroupKeepLayout->setRowStretch(3, 5);
247
248     // Costruction of the logical filter
249     QList<SUIT_SelectionFilter*> aListOfFilters;
250     aListOfFilters << new SMESH_TypeFilter (SMESH::SUBMESH)
251                    << new SMESH_TypeFilter (SMESH::GROUP);
252     mySubMeshOrGroupFilter =
253       new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR, /*takeOwnership=*/true);
254   }
255   else {
256     NodeSpecWidget         = 0;
257     SpinBoxTolerance       = 0;
258     GroupExclude           = 0;
259     ListExclude            = 0;
260     KeepFromButGroup       = 0;
261     SelectKeepNodesButton  = 0;
262     AddKeepNodesButton     = 0;
263     RemoveKeepNodesButton  = 0;
264     KeepList               = 0;
265     mySubMeshOrGroupFilter = 0;
266   }
267
268   ListCoincident = new QListWidget(GroupCoincident);
269   ListCoincident->setSelectionMode(QListWidget::ExtendedSelection);
270
271   DetectButton      = new QPushButton(tr("DETECT"),           GroupCoincident);
272   AddGroupButton    = new QPushButton(tr("SMESH_BUT_ADD"),    GroupCoincident);
273   RemoveGroupButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupCoincident);
274
275   SelectAllCB = new QCheckBox(tr("SELECT_ALL"), GroupCoincident);
276   ShowIDs = new QCheckBox(myAction == MERGE_ELEMENTS ? tr("SHOW_ELEMS_IDS") : tr("SHOW_NODES_IDS"), GroupCoincident);
277
278   aCoincidentLayout->addWidget(ListCoincident,    0, 0, 4, 2);
279   aCoincidentLayout->addWidget(DetectButton,      0, 2);
280   aCoincidentLayout->addWidget(AddGroupButton,    2, 2);
281   aCoincidentLayout->addWidget(RemoveGroupButton, 3, 2);
282   aCoincidentLayout->addWidget(SelectAllCB,       4, 0);
283   aCoincidentLayout->addWidget(ShowIDs,           4, 1);
284   aCoincidentLayout->setRowMinimumHeight(1, 10);
285   aCoincidentLayout->setRowStretch(1, 5);
286
287   /***************************************************************/
288   // Controls for editing the selected group
289
290   GroupEdit = new QGroupBox(myAction == MERGE_NODES ?
291                             tr("EDIT_SELECTED_NODE_GROUP") :
292                             tr("EDIT_SELECTED_ELEM_GROUP"), this);
293   QGridLayout* GroupEditLayout = new QGridLayout(GroupEdit);
294   GroupEditLayout->setSpacing(SPACING);
295   GroupEditLayout->setMargin(MARGIN);
296
297   ListEdit = new QListWidget(GroupEdit);
298   //ListEdit->setRowMode(QListBox::FixedNumber);
299   //ListEdit->setHScrollBarMode(QScrollView::AlwaysOn);
300   //ListEdit->setVScrollBarMode(QScrollView::AlwaysOff);
301   ListEdit->setFlow( QListView::LeftToRight );
302   ListEdit->setSelectionMode(QListWidget::ExtendedSelection);
303
304   AddElemButton = new QPushButton(GroupEdit);
305   AddElemButton->setIcon(IconAdd);
306   RemoveElemButton = new QPushButton(GroupEdit);
307   RemoveElemButton->setIcon(IconRemove);
308   SetFirstButton = new QPushButton(GroupEdit);
309   SetFirstButton->setIcon(IconFirst());
310
311   GroupEditLayout->addWidget(ListEdit,         0, 0, 2, 1);
312   GroupEditLayout->addWidget(AddElemButton,    0, 1);
313   GroupEditLayout->addWidget(RemoveElemButton, 0, 2);
314   GroupEditLayout->addWidget(SetFirstButton,   1, 1, 1, 2);
315
316   /***************************************************************/
317   GroupButtons = new QGroupBox(this);
318   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
319   GroupButtonsLayout->setSpacing(SPACING);
320   GroupButtonsLayout->setMargin(MARGIN);
321
322   buttonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons);
323   buttonOk->setAutoDefault(true);
324   buttonOk->setDefault(true);
325   buttonApply = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
326   buttonApply->setAutoDefault(true);
327   buttonCancel = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
328   buttonCancel->setAutoDefault(true);
329   buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
330   buttonHelp->setAutoDefault(true);
331
332   GroupButtonsLayout->addWidget(buttonOk);
333   GroupButtonsLayout->addSpacing(10);
334   GroupButtonsLayout->addWidget(buttonApply);
335   GroupButtonsLayout->addSpacing(10);
336   GroupButtonsLayout->addStretch();
337   GroupButtonsLayout->addWidget(buttonCancel);
338   GroupButtonsLayout->addWidget(buttonHelp);
339
340   /***************************************************************/
341   if (myAction == MERGE_NODES)
342   {
343     QWidget* LeftWdg = new QWidget( this );
344     QVBoxLayout* LeftLayout = new QVBoxLayout(LeftWdg);
345     LeftLayout->setSpacing(SPACING);
346     LeftLayout->setMargin(0);
347     LeftLayout->addWidget(TypeBox);
348     LeftLayout->addWidget(GroupMesh);
349     LeftLayout->addWidget(NodeSpecWidget);
350     LeftLayout->addWidget(GroupCoincident);
351     LeftLayout->addStretch();
352     LeftLayout->addWidget(GroupButtons);
353     LeftLayout->setStretch( 3, 10 );
354
355     QWidget* RightWdg = new QWidget( this );
356     QVBoxLayout* RightLayout = new QVBoxLayout(RightWdg);
357     RightLayout->setSpacing(SPACING);
358     RightLayout->setMargin(0);
359     RightLayout->addWidget(GroupExclude);
360     RightLayout->addWidget(GroupKeep);
361     RightLayout->addWidget(GroupEdit);
362     RightLayout->setStretch( 0, 4 );
363     RightLayout->setStretch( 1, 5 );
364
365     QHBoxLayout* DlgLayout = new QHBoxLayout(this);
366     DlgLayout->setSpacing(SPACING*2);
367     DlgLayout->setMargin(MARGIN);
368     DlgLayout->addWidget( LeftWdg );
369     DlgLayout->addWidget( RightWdg );
370   }
371   else
372   {
373     QVBoxLayout* DlgLayout = new QVBoxLayout(this);
374     DlgLayout->setSpacing(SPACING);
375     DlgLayout->setMargin(MARGIN);
376     DlgLayout->addWidget(TypeBox);
377     DlgLayout->addWidget(GroupMesh);
378     DlgLayout->addWidget(GroupCoincident);
379     DlgLayout->addWidget(GroupEdit);
380     DlgLayout->addWidget(GroupButtons);
381   }
382
383   GroupCoincident->hide();
384   GroupEdit->hide();
385
386   this->resize(10,10);
387
388   ShowIDs->setChecked( true );
389
390   Init(); // Initialisations
391 }
392
393 //=================================================================================
394 // function : ~SMESHGUI_MergeDlg()
395 // purpose  : Destroys the object and frees any allocated resources
396 //=================================================================================
397 SMESHGUI_MergeDlg::~SMESHGUI_MergeDlg()
398 {
399   delete myIdPreview;
400 }
401
402 //=================================================================================
403 // function : Init()
404 // purpose  :
405 //=================================================================================
406 void SMESHGUI_MergeDlg::Init()
407 {
408   if ( myAction == MERGE_NODES ) {
409     SpinBoxTolerance->RangeStepAndValidator(0.0, COORD_MAX, 0.00001, "len_tol_precision");
410     SpinBoxTolerance->SetValue(1e-05);
411   }
412
413   GroupType->button(0)->setChecked(true);
414
415   myEditCurrentArgument = (QWidget*)LineEditMesh;
416
417   myActor = 0;
418   mySubMeshOrGroup = SMESH::SMESH_subMesh::_nil();
419
420   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
421
422   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
423   myIsBusy = false;
424
425   /* signals and slots connections */
426   connect(buttonOk,     SIGNAL(clicked()), this, SLOT(ClickOnOk()));
427   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
428   connect(buttonApply,  SIGNAL(clicked()), this, SLOT(ClickOnApply()));
429   connect(buttonHelp,   SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
430
431   if ( KeepList )
432   {
433     connect(SelectKeepNodesButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument()));
434     connect(KeepFromButGroup, SIGNAL (buttonClicked(int)), SLOT(onKeepNodeSourceChanged(int)));
435     connect(AddKeepNodesButton, SIGNAL (clicked()), this, SLOT(onAddKeepNode()));
436     connect(RemoveKeepNodesButton, SIGNAL (clicked()), this, SLOT(onRemoveKeepNode()));
437     connect(KeepList, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectKeepNode()));
438   }
439   connect(SelectMeshButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument()));
440   connect(DetectButton, SIGNAL (clicked()), this, SLOT(onDetect()));
441   connect(ListCoincident, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectGroup()));
442   connect(AddGroupButton, SIGNAL (clicked()), this, SLOT(onAddGroup()));
443   connect(RemoveGroupButton, SIGNAL (clicked()), this, SLOT(onRemoveGroup()));
444   connect(SelectAllCB, SIGNAL(toggled(bool)), this, SLOT(onSelectAll(bool)));
445   connect(ShowIDs, SIGNAL(toggled(bool)), this, SLOT(onSelectGroup()));
446   connect(ListEdit, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectElementFromGroup()));
447   connect(AddElemButton, SIGNAL (clicked()), this, SLOT(onAddElement()));
448   connect(RemoveElemButton, SIGNAL (clicked()), this, SLOT(onRemoveElement()));
449   connect(SetFirstButton, SIGNAL( clicked() ), this, SLOT( onSetFirst()));
450   connect(GroupType, SIGNAL(buttonClicked(int)), this, SLOT(onTypeChanged(int)));
451
452   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
453   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
454   /* to close dialog if study change */
455   connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
456   connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this,  SLOT(onOpenView()));
457   connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
458   // Init Mesh field from selection
459   SelectionIntoArgument();
460
461   // Update Buttons
462   updateControls();
463   
464   if ( myAction == MERGE_NODES )
465     myHelpFileName = "merging_nodes.html";
466   else
467     myHelpFileName = "merging_elements.html";
468 }
469
470 //=================================================================================
471 // function : FindGravityCenter()
472 // purpose  :
473 //=================================================================================
474 void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap,
475                                           std::vector<int>&      theIDs,
476                                           std::list< gp_XYZ > &  theGrCentersXYZ)
477 {
478   if (!myActor)
479     return;
480
481   SMDS_Mesh* aMesh = 0;
482   aMesh = myActor->GetObject()->GetMesh();
483   if (!aMesh)
484     return;
485
486   int nbNodes;
487
488   theIDs.reserve( theElemsIdMap.Extent() );
489   TColStd_MapIteratorOfMapOfInteger idIter( theElemsIdMap );
490   for( ; idIter.More(); idIter.Next() ) {
491     const SMDS_MeshElement* anElem = aMesh->FindElement(idIter.Key());
492     if ( !anElem )
493       continue;
494     theIDs.push_back( idIter.Key() );
495
496     gp_XYZ anXYZ(0., 0., 0.);
497     SMDS_ElemIteratorPtr nodeIt = anElem->nodesIterator();
498     for ( nbNodes = 0; nodeIt->more(); nbNodes++ ) {
499       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
500       anXYZ.Add( gp_XYZ( node->X(), node->Y(), node->Z() ) );
501     }
502     anXYZ.Divide( nbNodes );
503     
504     theGrCentersXYZ.push_back( anXYZ );
505   }
506 }
507
508 //=================================================================================
509 // function : ClickOnApply()
510 // purpose  :
511 //=================================================================================
512 bool SMESHGUI_MergeDlg::ClickOnApply()
513 {
514   if (mySMESHGUI->isActiveStudyLocked() || myMesh->_is_nil())
515     return false;
516
517   try {
518     if (myTypeId == TYPE_AUTO)
519       onDetect();
520
521     SUIT_OverrideCursor aWaitCursor;
522     SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
523
524     SMESH::long_array_var anIds = new SMESH::long_array;
525     SMESH::array_of_long_array_var aGroupsOfElements = new SMESH::array_of_long_array;
526
527     if ( ListCoincident->count() == 0) {
528       if ( myAction == MERGE_NODES )
529         SUIT_MessageBox::warning(this,
530                                  tr("SMESH_WARNING"),
531                                  tr("SMESH_NO_NODES_DETECTED"));
532       else
533         SUIT_MessageBox::warning(this,
534                                  tr("SMESH_WARNING"),
535                                  tr("SMESH_NO_ELEMENTS_DETECTED"));
536       return false;
537     }
538
539     aGroupsOfElements->length(ListCoincident->count());
540
541     int anArrayNum = 0;
542     for (int i = 0; i < ListCoincident->count(); i++) {
543       QStringList aListIds = ListCoincident->item(i)->text().split(" ", QString::SkipEmptyParts);
544
545       anIds->length(aListIds.count());
546       for (int i = 0; i < aListIds.count(); i++)
547         anIds[i] = aListIds[i].toInt();
548
549       aGroupsOfElements[anArrayNum++] = anIds.inout();
550     }
551
552     SMESH::ListOfIDSources_var nodesToKeep;
553     SMESH::IDSource_wrap tmpIdSource;
554     if ( myAction == MERGE_NODES )
555     {
556       nodesToKeep = new SMESH::ListOfIDSources();
557       int i, nb = KeepList->count();
558       if ( isKeepNodesIDsSelection() )
559       {
560         SMESH::long_array_var anIdList = new SMESH::long_array();
561         anIdList->length(nb);
562         for (i = 0; i < nb; i++)
563           anIdList[i] = KeepList->item(i)->text().toInt();
564
565         if ( nb > 0 )
566         {
567           tmpIdSource = aMeshEditor->MakeIDSource( anIdList, SMESH::NODE );
568           nodesToKeep->length( 1 );
569           nodesToKeep[0] = SMESH::SMESH_IDSource::_duplicate( tmpIdSource.in() );
570         }
571       }
572       else
573       {
574         nodesToKeep->length( nb );
575         int nbObj = 0;
576         for (i = 0; i < nb; i++)
577         {
578           QString entry = KeepList->item( i )->data( Qt::UserRole ).toString();
579           Handle(SALOME_InteractiveObject) anIO =
580             new SALOME_InteractiveObject( entry.toStdString().c_str(), "SMESH" );
581           SMESH::SMESH_IDSource_var idSrc =
582             SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( anIO );
583           if ( !idSrc->_is_nil() )
584             nodesToKeep[ nbObj++ ] = SMESH::SMESH_IDSource::_duplicate( idSrc );
585         }
586         nodesToKeep->length( nbObj );
587       }
588       KeepList->clear();
589     }
590
591     if( myAction == MERGE_NODES )
592       aMeshEditor->MergeNodes( aGroupsOfElements.inout(), nodesToKeep, AvoidMakingHoles->isChecked() );
593     else
594       aMeshEditor->MergeElements( aGroupsOfElements.inout() );
595
596     if ( myTypeId == TYPE_AUTO ) {
597       if ( myAction == MERGE_NODES )
598         SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"),
599                                      tr("SMESH_MERGED_NODES").arg(QString::number(ListCoincident->count()).toLatin1().data()));
600       else
601         SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"),
602                                      tr("SMESH_MERGED_ELEMENTS").arg(QString::number(ListCoincident->count()).toLatin1().data()));
603     }
604     if ( & nodesToKeep.in() )
605       nodesToKeep->length(0); // release before tmpIdSource calls UnRegister()
606
607   }
608   catch(...) {
609   }
610
611   ListCoincident->clear();
612
613   myEditCurrentArgument = (QWidget*)LineEditMesh;
614
615   SMESH::UpdateView();
616   SMESHGUI::Modified();
617
618   return true;
619 }
620
621 //=================================================================================
622 // function : ClickOnOk()
623 // purpose  :
624 //=================================================================================
625 void SMESHGUI_MergeDlg::ClickOnOk()
626 {
627   if (ClickOnApply())
628     reject();
629 }
630
631 //=================================================================================
632 // function : reject()
633 // purpose  :
634 //=================================================================================
635 void SMESHGUI_MergeDlg::reject()
636 {
637   myIdPreview->SetPointsLabeled(false);
638   SMESH::SetPointRepresentation(false);
639   disconnect(mySelectionMgr, 0, this, 0);
640   disconnect(mySMESHGUI, 0, this, 0);
641   mySMESHGUI->ResetState();
642
643   mySelectionMgr->clearFilters();
644   //mySelectionMgr->clearSelected();
645
646   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
647     aViewWindow->SetSelectionMode(ActorSelection);
648
649   QDialog::reject();
650 }
651
652 //=================================================================================
653 // function : onOpenView()
654 // purpose  :
655 //=================================================================================
656 void SMESHGUI_MergeDlg::onOpenView()
657 {
658   if ( mySelector ) {
659     SMESH::SetPointRepresentation(false);
660   }
661   else {
662     mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
663     ActivateThisDialog();
664   }
665 }
666
667 //=================================================================================
668 // function : onCloseView()
669 // purpose  :
670 //=================================================================================
671 void SMESHGUI_MergeDlg::onCloseView()
672 {
673   DeactivateActiveDialog();
674   mySelector = 0;
675 }
676
677 //=================================================================================
678 // function : ClickOnHelp()
679 // purpose  :
680 //=================================================================================
681 void SMESHGUI_MergeDlg::ClickOnHelp()
682 {
683   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
684   if (app) 
685     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
686   else {
687     QString platform;
688 #ifdef WIN32
689     platform = "winapplication";
690 #else
691     platform = "application";
692 #endif
693     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
694                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
695                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
696                                                                  platform)).
697                              arg(myHelpFileName));
698   }
699 }
700
701 //=================================================================================
702 // function : onEditGroup()
703 // purpose  :
704 //=================================================================================
705 void SMESHGUI_MergeDlg::onEditGroup()
706 {
707   QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
708   if ( selItems.count() != 1 ) {
709     ListEdit->clear();
710     return;
711   }
712
713   QStringList aNewIds;
714
715   for (int i = 0; i < ListEdit->count(); i++ )
716     aNewIds.append(ListEdit->item(i)->text());
717
718   ListCoincident->clearSelection();
719   selItems.first()->setText(aNewIds.join(" "));
720   selItems.first()->setSelected(true);
721 }
722
723 //=================================================================================
724 // function : updateControls()
725 // purpose  :
726 //=================================================================================
727 void SMESHGUI_MergeDlg::updateControls()
728 {
729   if (ListEdit->count() == 0)
730     SetFirstButton->setEnabled(false);
731
732   bool groupsEmpty = ( myTypeId != TYPE_AUTO );
733   for (int i = 0; i < ListCoincident->count() && groupsEmpty; i++) {
734     QStringList aListIds = ListCoincident->item(i)->text().split(" ", QString::SkipEmptyParts);
735     groupsEmpty = ( aListIds.count() < 2 );
736   }
737   bool enable = ( !myMesh->_is_nil() && !groupsEmpty );
738   buttonOk->setEnabled(enable);
739   buttonApply->setEnabled(enable);
740   DetectButton->setEnabled( !myMesh->_is_nil() );
741
742   if ( myAction == MERGE_NODES )
743   {
744     bool has2ndOrder = (( !myMesh->_is_nil() ) &&
745                         ( myMesh->NbEdgesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 ||
746                           myMesh->NbFacesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 ||
747                           myMesh->NbVolumesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 ));
748
749     SeparateCornersAndMedium->setEnabled( has2ndOrder );
750
751     if ( myEditCurrentArgument != KeepList )
752     {
753       AddKeepNodesButton->setEnabled( false );
754       RemoveKeepNodesButton->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     SMESH::SMESH_IDSource_var src;
780     if ( mySubMeshOrGroup->_is_nil() ) src = SMESH::SMESH_IDSource::_duplicate( myMesh );
781     else                               src = SMESH::SMESH_IDSource::_duplicate( mySubMeshOrGroup );
782
783     switch (myAction) {
784     case MERGE_NODES :
785       for ( int i = 0; GroupExclude->isChecked() && i < ListExclude->count(); i++ ) {
786         if ( ListExclude->item( i )->checkState() == Qt::Checked ) {
787           aExcludeGroups->length( aExcludeGroups->length()+1 );
788           aExcludeGroups[ aExcludeGroups->length()-1 ] = SMESH::SMESH_IDSource::_duplicate( myGroups[i] );
789         }
790       }
791       aMeshEditor->FindCoincidentNodesOnPartBut(src.in(),
792                                                 SpinBoxTolerance->GetValue(), 
793                                                 aGroupsArray.out(),
794                                                 aExcludeGroups.in(),
795                                                 SeparateCornersAndMedium->isEnabled() &&
796                                                 SeparateCornersAndMedium->isChecked());
797       break;
798     case MERGE_ELEMENTS :
799       aMeshEditor->FindEqualElements(src.in(), aGroupsArray.out());
800       break;
801     }
802     
803     for (int i = 0; i < (int)aGroupsArray->length(); i++) {
804       SMESH::long_array& aGroup = aGroupsArray[i];
805
806       QStringList anIDs;
807       for (int j = 0; j < (int)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        !isKeepNodesIDsSelection() )
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        !isKeepNodesIDsSelection() )
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 == SelectKeepNodesButton && send )
1117   {
1118     myEditCurrentArgument = (QWidget*)KeepList;
1119     KeepList->setWrapping( isKeepNodesIDsSelection() );
1120     if ( isKeepNodesIDsSelection() )
1121     {
1122       SMESH::SetPointRepresentation( true );
1123       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1124         aViewWindow->SetSelectionMode( NodeSelection );
1125     }
1126     else
1127     {
1128       SMESH::SetPointRepresentation( false );
1129       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1130         aViewWindow->SetSelectionMode( ActorSelection );
1131       mySelectionMgr->installFilter( mySubMeshOrGroupFilter );
1132     }
1133   }
1134
1135   myEditCurrentArgument->setFocus();
1136   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
1137   SelectionIntoArgument();
1138 }
1139
1140 //=================================================================================
1141 // function : SelectionIntoArgument()
1142 // purpose  : Called when selection has changed or other case
1143 //=================================================================================
1144 void SMESHGUI_MergeDlg::SelectionIntoArgument()
1145 {
1146   if (myEditCurrentArgument == (QWidget*)LineEditMesh)
1147   {
1148     QString aString = "";
1149     LineEditMesh->setText(aString);
1150
1151     ListCoincident->clear();
1152     ListEdit->clear();
1153     myActor = 0;
1154     myMesh = SMESH::SMESH_Mesh::_nil();
1155     QString aCurrentEntry = myEntry;
1156
1157     int nbSel = SMESH::GetNameOfSelectedIObjects(mySelectionMgr, aString);
1158     if (nbSel != 1) {
1159       myIdPreview->SetPointsLabeled(false);
1160       SMESH::SetPointRepresentation(false);
1161       mySelectionMgr->clearFilters();
1162       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1163         aViewWindow->SetSelectionMode(ActorSelection);
1164       return;
1165     }
1166
1167     SALOME_ListIO aList;
1168     mySelectionMgr->selectedObjects(aList);
1169
1170     Handle(SALOME_InteractiveObject) IO = aList.First();
1171     myEntry = IO->getEntry();
1172     myMesh = SMESH::GetMeshByIO(IO);
1173
1174     if ( myEntry != aCurrentEntry && KeepList )
1175       KeepList->clear();
1176
1177     if (myMesh->_is_nil())
1178       return;
1179
1180     LineEditMesh->setText(aString);
1181
1182     myActor = SMESH::FindActorByEntry(IO->getEntry());
1183     if (!myActor)
1184       myActor = SMESH::FindActorByObject(myMesh);
1185
1186     if ( myActor && myTypeId == TYPE_MANUAL && mySelector->IsSelectionEnabled() ) {
1187       mySubMeshOrGroup = SMESH::SMESH_IDSource::_nil();
1188       mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter);
1189
1190       if ((!SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(IO)->_is_nil() || //SUBMESH OR GROUP
1191            !SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(IO)->_is_nil()) &&
1192           !SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(IO)->_is_nil())
1193         mySubMeshOrGroup = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(IO);
1194
1195       if (myAction == MERGE_NODES) {
1196         SMESH::SetPointRepresentation(true);
1197         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1198           aViewWindow->SetSelectionMode(NodeSelection);
1199       }
1200       else
1201         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1202           aViewWindow->SetSelectionMode(CellSelection);
1203     }
1204
1205     // process groups
1206     if ( myAction == MERGE_NODES && !myMesh->_is_nil() && myEntry != aCurrentEntry ) {
1207       myGroups.clear();
1208       ListExclude->clear();
1209       SMESH::ListOfGroups_var aListOfGroups = myMesh->GetGroups();
1210       GroupExclude->setEnabled( aListOfGroups->length() > 0 );
1211       for( int i = 0, n = aListOfGroups->length(); i < n; i++ ) {
1212         SMESH::SMESH_GroupBase_var aGroup = aListOfGroups[i];
1213         if ( !aGroup->_is_nil() ) { // && aGroup->GetType() == SMESH::NODE
1214           QString aGroupName( aGroup->GetName() );
1215           if ( !aGroupName.isEmpty() ) {
1216             myGroups.append(SMESH::SMESH_GroupBase::_duplicate(aGroup));
1217             QListWidgetItem* item = new QListWidgetItem( aGroupName );
1218             item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
1219             item->setCheckState( Qt::Unchecked );
1220             ListExclude->addItem( item );
1221           }
1222         }
1223       }
1224     }
1225
1226     updateControls();
1227   }
1228
1229   else if (myEditCurrentArgument == (QWidget*)KeepList && KeepList)
1230   {
1231     AddKeepNodesButton->setEnabled( false );
1232     RemoveKeepNodesButton->setEnabled( false );
1233     if ( isKeepNodesIDsSelection() )
1234     {
1235       if (!myMesh->_is_nil() && !myActor)
1236         myActor = SMESH::FindActorByObject(myMesh);
1237
1238       if ( mySelector && myActor )
1239       {
1240         KeepList->clearSelection();
1241         QString anIDs = "";
1242         int aNbNodes = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), anIDs);
1243         if (aNbNodes > 0)
1244         {
1245           QStringList anNodes = anIDs.split( " ", QString::SkipEmptyParts);
1246           QList<QListWidgetItem*> listItemsToSel;
1247           QListWidgetItem* anItem;
1248           int nbFound = 0;
1249           for (QStringList::iterator it = anNodes.begin(); it != anNodes.end(); ++it)
1250           {
1251             QList<QListWidgetItem*> found = KeepList->findItems(*it, Qt::MatchExactly);
1252             foreach(anItem, found)
1253               if (!anItem->isSelected())
1254                 listItemsToSel.push_back(anItem);
1255             nbFound += found.count();
1256           }
1257           bool blocked = KeepList->signalsBlocked();
1258           KeepList->blockSignals(true);
1259           foreach(anItem, listItemsToSel) anItem->setSelected(true);
1260           KeepList->blockSignals(blocked);
1261           //onSelectKeepNode();
1262           AddKeepNodesButton->setEnabled( nbFound < aNbNodes );
1263           RemoveKeepNodesButton->setEnabled( nbFound > 0 );
1264         }
1265       }
1266     }
1267     else if ( !myMesh->_is_nil() )
1268     {
1269       SALOME_ListIO aList;
1270       mySelectionMgr->selectedObjects(aList);
1271       bool hasNewSelected = false;
1272       SALOME_ListIteratorOfListIO anIt (aList);
1273       for ( ; anIt.More() && !hasNewSelected; anIt.Next())
1274         if ( anIt.Value()->hasEntry() )
1275           hasNewSelected = isNewKeepNodesGroup( anIt.Value()->getEntry() );
1276
1277       AddKeepNodesButton->setEnabled( hasNewSelected );
1278       //RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() );
1279     }
1280   }
1281 }
1282
1283 //=================================================================================
1284 // function : DeactivateActiveDialog()
1285 // purpose  :
1286 //=================================================================================
1287 void SMESHGUI_MergeDlg::DeactivateActiveDialog()
1288 {
1289   if (TypeBox->isEnabled()) {
1290     TypeBox->setEnabled(false);
1291     GroupMesh->setEnabled(false);
1292     GroupCoincident->setEnabled(false);
1293     GroupEdit->setEnabled(false);
1294     GroupButtons->setEnabled(false);
1295     if (myAction == MERGE_NODES)
1296     {
1297       GroupExclude->setEnabled(false);
1298       GroupKeep->setEnabled(false);
1299     }
1300     mySMESHGUI->ResetState();
1301     mySMESHGUI->SetActiveDialogBox(0);
1302   }
1303
1304   mySelectionMgr->clearSelected();
1305   disconnect(mySelectionMgr, 0, this, 0);
1306 }
1307
1308 //=================================================================================
1309 // function : ActivateThisDialog()
1310 // purpose  :
1311 //=================================================================================
1312 void SMESHGUI_MergeDlg::ActivateThisDialog()
1313 {
1314   /* Emit a signal to deactivate the active dialog */
1315   mySMESHGUI->EmitSignalDeactivateDialog();
1316   TypeBox->setEnabled(true);
1317   GroupMesh->setEnabled(true);
1318   GroupCoincident->setEnabled(true);
1319   GroupEdit->setEnabled(true);
1320   GroupButtons->setEnabled(true);
1321   if (myAction == MERGE_NODES)
1322   {
1323     GroupExclude->setEnabled(false);
1324     GroupKeep->setEnabled(false);
1325   }
1326
1327   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
1328   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
1329   SelectionIntoArgument();
1330 }
1331
1332 //=================================================================================
1333 // function : enterEvent()
1334 // purpose  :
1335 //=================================================================================
1336 void SMESHGUI_MergeDlg::enterEvent (QEvent*)
1337 {
1338   if ( !TypeBox->isEnabled() ) {
1339     SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
1340     if ( aViewWindow && !mySelector) {
1341       mySelector = aViewWindow->GetSelector();
1342     }
1343     ActivateThisDialog();
1344   }
1345 }
1346
1347 //=================================================================================
1348 // function : keyPressEvent()
1349 // purpose  :
1350 //=================================================================================
1351 void SMESHGUI_MergeDlg::keyPressEvent( QKeyEvent* e)
1352 {
1353   QDialog::keyPressEvent( e );
1354   if ( e->isAccepted() )
1355     return;
1356
1357   if ( e->key() == Qt::Key_F1 ) {
1358     e->accept();
1359     ClickOnHelp();
1360   }
1361 }
1362
1363 //=================================================================================
1364 // function : onTypeChanged()
1365 // purpose  : the type radio button management
1366 //=================================================================================
1367 void SMESHGUI_MergeDlg::onTypeChanged (int id)
1368 {
1369   if (myTypeId == id)
1370     return;
1371
1372   myTypeId = id;
1373   switch (id)
1374   {
1375   case TYPE_AUTO: // automatic
1376
1377     myIdPreview->SetPointsLabeled(false);
1378     SMESH::SetPointRepresentation(false);
1379     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1380       aViewWindow->SetSelectionMode(ActorSelection);
1381     mySelectionMgr->clearFilters();
1382     GroupCoincident->hide();
1383     GroupEdit->hide();
1384
1385     GroupMesh->hide(); // <--- a trick to make the dialog take a minimal size
1386     GroupMesh->show();
1387     break;
1388
1389   case TYPE_MANUAL: // manual
1390
1391     SMESH::UpdateView();
1392
1393     // Costruction of the logical filter
1394     SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter (SMESH::MESHorSUBMESH);
1395     SMESH_TypeFilter* aSmeshGroupFilter    = new SMESH_TypeFilter (SMESH::GROUP);
1396     
1397     QList<SUIT_SelectionFilter*> aListOfFilters;
1398     if (aMeshOrSubMeshFilter) aListOfFilters.append(aMeshOrSubMeshFilter);
1399     if (aSmeshGroupFilter)    aListOfFilters.append(aSmeshGroupFilter);
1400     
1401     myMeshOrSubMeshOrGroupFilter =
1402       new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR, true);
1403
1404     if (myAction == MERGE_NODES) {
1405       SMESH::SetPointRepresentation(true);
1406       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1407         if( mySelector->IsSelectionEnabled() )
1408           aViewWindow->SetSelectionMode(NodeSelection);
1409     }
1410     else {
1411       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1412         if( mySelector->IsSelectionEnabled() )
1413           aViewWindow->SetSelectionMode(CellSelection);
1414     }
1415     GroupCoincident->show();
1416     GroupEdit->show();
1417     break;
1418   }
1419   SelectionIntoArgument();
1420
1421   updateControls();
1422
1423   qApp->processEvents();
1424   updateGeometry();
1425   resize(10,10);
1426 }
1427
1428 //=======================================================================
1429 //function : isKeepNodesIDsSelection
1430 //purpose  : Return true of Nodes to keep are selected by IDs
1431 //=======================================================================
1432
1433 bool SMESHGUI_MergeDlg::isKeepNodesIDsSelection()
1434 {
1435   return KeepFromButGroup && KeepFromButGroup->checkedId() == 0;
1436 }
1437
1438 //=======================================================================
1439 //function : isNewKeepNodesGroup
1440 //purpose  : Return true if an object with given entry is NOT present in KeepList
1441 //=======================================================================
1442
1443 bool SMESHGUI_MergeDlg::isNewKeepNodesGroup( const char* entry )
1444 {
1445   if ( !entry || isKeepNodesIDsSelection() )
1446     return false;
1447
1448   for ( int i = 0; i < KeepList->count(); i++ )
1449     if ( KeepList->item( i )->data( Qt::UserRole ).toString() == entry )
1450       return false;
1451
1452   return true;
1453 }
1454
1455 //=======================================================================
1456 //function : onAddKeepNode
1457 //purpose  : SLOT called when [Add] of Nodes To Keep group is pressed
1458 //=======================================================================
1459
1460 void SMESHGUI_MergeDlg::onAddKeepNode()
1461 {
1462   if ( myIsBusy )
1463     return;
1464   myIsBusy = true;
1465
1466   if ( isKeepNodesIDsSelection() )
1467   {
1468     //KeepList->clearSelection();
1469     QString anIDs = "";
1470     int aNbNodes = 0;
1471     if ( myActor )
1472       aNbNodes = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), anIDs);
1473     if (aNbNodes > 0)
1474     {
1475       QStringList anNodes = anIDs.split( " ", QString::SkipEmptyParts);
1476       QList<QListWidgetItem*> listItemsToSel;
1477       QListWidgetItem* anItem;
1478       for (QStringList::iterator it = anNodes.begin(); it != anNodes.end(); ++it)
1479       {
1480         QList<QListWidgetItem*> found = KeepList->findItems(*it, Qt::MatchExactly);
1481         if (found.count() == 0) {
1482           anItem = new QListWidgetItem(*it);
1483           KeepList->addItem(anItem);
1484           if (!anItem->isSelected())
1485             listItemsToSel.push_back(anItem);
1486         }
1487         else {
1488           foreach(anItem, found)
1489             if (!anItem->isSelected())
1490               listItemsToSel.push_back(anItem);
1491         }
1492       }
1493       bool blocked = KeepList->signalsBlocked();
1494       KeepList->blockSignals(true);
1495       foreach(anItem, listItemsToSel) anItem->setSelected(true);
1496       KeepList->blockSignals(blocked);
1497       //onSelectKeepNode();
1498     }
1499     RemoveKeepNodesButton->setEnabled( aNbNodes > 0 );
1500   }
1501   else
1502   {
1503     SALOME_ListIO aList;
1504     mySelectionMgr->selectedObjects(aList);
1505     SALOME_ListIteratorOfListIO anIt (aList);
1506     for ( ; anIt.More(); anIt.Next()) {
1507       Handle(SALOME_InteractiveObject) anIO = anIt.Value();
1508       if ( isNewKeepNodesGroup( anIO->getEntry() ))
1509       {
1510         QListWidgetItem* anItem = new QListWidgetItem( anIO->getName() );
1511         anItem->setData( Qt::UserRole, QString( anIO->getEntry() ));
1512         KeepList->addItem(anItem);
1513       }
1514     }
1515     //RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() );
1516   }
1517
1518   AddKeepNodesButton->setEnabled( false );
1519
1520   myIsBusy = false;
1521 }
1522
1523 //=======================================================================
1524 //function : onRemoveKeepNode
1525 //purpose  : SLOT called when [Remove] of Nodes To Keep group is pressed
1526 //=======================================================================
1527
1528 void SMESHGUI_MergeDlg::onRemoveKeepNode()
1529 {
1530   // if ( isKeepNodesIDsSelection() )
1531   // {
1532   // }
1533   // else
1534   {
1535     QList<QListWidgetItem*> selItems = KeepList->selectedItems();
1536     QListWidgetItem* item;
1537     foreach(item, selItems) delete item;
1538   }
1539   if ( isKeepNodesIDsSelection() )
1540   {
1541     AddKeepNodesButton->setEnabled( false );
1542   }
1543   RemoveKeepNodesButton->setEnabled( false );
1544 }
1545
1546 //=======================================================================
1547 //function : onSelectKeepNode
1548 //purpose  : SLOT called when selection in KeepList changes
1549 //=======================================================================
1550
1551 void SMESHGUI_MergeDlg::onSelectKeepNode()
1552 {
1553   if ( myIsBusy || !isEnabled() ) return;
1554   myIsBusy = true;
1555
1556   if ( isKeepNodesIDsSelection() )
1557   {
1558     if ( myActor )
1559     {
1560       mySelectionMgr->clearSelected();
1561       TColStd_MapOfInteger aIndexes;
1562       QList<QListWidgetItem*> selItems = KeepList->selectedItems();
1563       QListWidgetItem* anItem;
1564       foreach(anItem, selItems) aIndexes.Add(anItem->text().toInt());
1565       mySelector->AddOrRemoveIndex(myActor->getIO(), aIndexes, false);
1566       SALOME_ListIO aList;
1567       aList.Append(myActor->getIO());
1568       mySelectionMgr->setSelectedObjects(aList,false);
1569
1570       AddKeepNodesButton->setEnabled( false );
1571       RemoveKeepNodesButton->setEnabled( aIndexes.Extent() > 0 );
1572     }
1573   }
1574   else
1575   {
1576     RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() );
1577   }
1578   myIsBusy = false;
1579 }
1580
1581 //=======================================================================
1582 //function : onKeepNodeSourceChanged
1583 //purpose  : SLOT called when type of source of Nodes To Keep change from
1584 //           IDs to groups or vice versa
1585 //=======================================================================
1586
1587 void SMESHGUI_MergeDlg::onKeepNodeSourceChanged(int isGroup)
1588 {
1589   KeepList->clear();
1590   SelectKeepNodesButton->click();
1591 }