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