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