Salome HOME
Merge from BR_phase16 branch (09/12/09)
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_RemoveNodesDlg.cxx
1 //  Copyright (C) 2007-2008  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.
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 // SMESH SMESHGUI : GUI for SMESH component
23 // File   : SMESHGUI_RemoveNodesDlg.cxx
24 // Author : Nicolas REJNERI, Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_RemoveNodesDlg.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_IdValidator.h"
34 #include "SMESHGUI_FilterDlg.h"
35
36 #include <SMESH_Actor.h>
37 #include <SMDS_Mesh.hxx>
38
39 // SALOME GUI includes
40 #include <SUIT_ResourceMgr.h>
41 #include <SUIT_Desktop.h>
42 #include <SUIT_Session.h>
43 #include <SUIT_MessageBox.h>
44
45 #include <LightApp_Application.h>
46 #include <LightApp_SelectionMgr.h>
47 #include <SalomeApp_Tools.h>
48
49 #include <SVTK_Selector.h>
50 #include <SVTK_ViewModel.h>
51 #include <SVTK_ViewWindow.h>
52 #include <SALOME_ListIO.hxx>
53
54 // OCCT includes
55 #include <TColStd_MapOfInteger.hxx>
56
57 // Qt includes
58 #include <QGroupBox>
59 #include <QLabel>
60 #include <QLineEdit>
61 #include <QPushButton>
62 #include <QRadioButton>
63 #include <QVBoxLayout>
64 #include <QHBoxLayout>
65 #include <QKeyEvent>
66 #include <QButtonGroup>
67
68 // IDL includes
69 #include <SALOMEconfig.h>
70 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
71
72 #define SPACING 6
73 #define MARGIN  11
74
75 //=================================================================================
76 // class    : SMESHGUI_RemoveNodesDlg()
77 // purpose  :
78 //=================================================================================
79 SMESHGUI_RemoveNodesDlg
80 ::SMESHGUI_RemoveNodesDlg(SMESHGUI* theModule)
81   : QDialog(SMESH::GetDesktop(theModule)),
82     mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
83     mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
84     mySMESHGUI(theModule),
85     myBusy(false),
86     myFilterDlg(0)
87 {
88   setModal( false );
89   setAttribute( Qt::WA_DeleteOnClose, true );
90   setWindowTitle(tr("SMESH_REMOVE_NODES_TITLE"));
91   setSizeGripEnabled(true);
92   
93   QPixmap image0 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_DLG_REM_NODE")));
94   QPixmap image1 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
95
96   QVBoxLayout* SMESHGUI_RemoveNodesDlgLayout = new QVBoxLayout(this);
97   SMESHGUI_RemoveNodesDlgLayout->setSpacing(SPACING);
98   SMESHGUI_RemoveNodesDlgLayout->setMargin(MARGIN);
99
100   /***************************************************************/
101   GroupConstructors = new QGroupBox(tr("SMESH_NODES"), this);
102   QButtonGroup* ButtonGroup = new QButtonGroup(this);
103   QHBoxLayout* GroupConstructorsLayout = new QHBoxLayout(GroupConstructors);
104   GroupConstructorsLayout->setSpacing(SPACING);
105   GroupConstructorsLayout->setMargin(MARGIN);
106
107   Constructor1 = new QRadioButton(GroupConstructors);
108   Constructor1->setIcon(image0);
109   Constructor1->setChecked(true);
110
111   GroupConstructorsLayout->addWidget(Constructor1);
112   ButtonGroup->addButton(Constructor1, 0);
113
114   /***************************************************************/
115   GroupC1 = new QGroupBox(tr("SMESH_REMOVE"), this);
116   QHBoxLayout* GroupC1Layout = new QHBoxLayout(GroupC1);
117   GroupC1Layout->setSpacing(SPACING);
118   GroupC1Layout->setMargin(MARGIN);
119
120   TextLabelC1A1 = new QLabel(tr("SMESH_ID_NODES"), GroupC1);
121   SelectButtonC1A1 = new QPushButton(GroupC1);
122   SelectButtonC1A1->setIcon(image1);
123   LineEditC1A1 = new QLineEdit(GroupC1);
124   LineEditC1A1->setValidator(new SMESHGUI_IdValidator(this));
125   QPushButton* filterBtn = new QPushButton( tr( "SMESH_BUT_FILTER" ), GroupC1 );
126   connect(filterBtn,   SIGNAL(clicked()), this, SLOT(setFilters()));
127
128   GroupC1Layout->addWidget(TextLabelC1A1);
129   GroupC1Layout->addWidget(SelectButtonC1A1);
130   GroupC1Layout->addWidget(LineEditC1A1);
131   GroupC1Layout->addWidget(filterBtn );
132
133   /***************************************************************/
134   GroupButtons = new QGroupBox(this);
135   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
136   GroupButtonsLayout->setSpacing(SPACING);
137   GroupButtonsLayout->setMargin(MARGIN);
138
139   buttonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons);
140   buttonOk->setAutoDefault(true);
141   buttonOk->setDefault(true);
142   buttonApply = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
143   buttonApply->setAutoDefault(true);
144   buttonCancel = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
145   buttonCancel->setAutoDefault(true);
146   buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
147   buttonHelp->setAutoDefault(true);
148
149   GroupButtonsLayout->addWidget(buttonOk);
150   GroupButtonsLayout->addSpacing(10);
151   GroupButtonsLayout->addWidget(buttonApply);
152   GroupButtonsLayout->addSpacing(10);
153   GroupButtonsLayout->addStretch();
154   GroupButtonsLayout->addWidget(buttonCancel);
155   GroupButtonsLayout->addWidget(buttonHelp);
156
157   /***************************************************************/
158   SMESHGUI_RemoveNodesDlgLayout->addWidget(GroupConstructors);
159   SMESHGUI_RemoveNodesDlgLayout->addWidget(GroupC1);
160   SMESHGUI_RemoveNodesDlgLayout->addWidget(GroupButtons);
161
162   myHelpFileName = "removing_nodes_and_elements_page.html#removing_nodes_anchor";
163
164   Init(); /* Initialisations */
165 }
166
167 //=================================================================================
168 // function : ~SMESHGUI_RemoveNodesDlg()
169 // purpose  : Destroys the object and frees any allocated resources
170 //=================================================================================
171 SMESHGUI_RemoveNodesDlg::~SMESHGUI_RemoveNodesDlg()
172 {
173   if ( myFilterDlg ) {
174     myFilterDlg->setParent( 0 );
175     delete myFilterDlg;
176     myFilterDlg = 0;
177   }
178 }
179
180 //=================================================================================
181 // function : Init()
182 // purpose  :
183 //=================================================================================
184 void SMESHGUI_RemoveNodesDlg::Init()
185 {
186   myConstructorId = 0;
187   Constructor1->setChecked(true);
188   myEditCurrentArgument = LineEditC1A1;
189
190   myNbOkNodes = 0;
191   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
192   myActor = 0;
193   myBusy = false;
194
195   /* signals and slots connections */
196   connect(buttonOk,     SIGNAL(clicked()), this, SLOT(ClickOnOk()));
197   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(ClickOnCancel()));
198   connect(buttonApply,  SIGNAL(clicked()), this, SLOT(ClickOnApply()));
199   connect(buttonHelp,   SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
200
201   connect(SelectButtonC1A1, SIGNAL (clicked()),   this, SLOT(SetEditCurrentArgument()));
202   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
203   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
204   /* to close dialog if study change */
205   connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(ClickOnCancel()));
206   connect(myEditCurrentArgument, SIGNAL(textChanged(const QString&)),
207           SLOT(onTextChange(const QString&)));
208   
209   SMESH::SetPointRepresentation(true);
210   
211   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
212     aViewWindow->SetSelectionMode(NodeSelection);
213
214   SelectionIntoArgument();
215 }
216
217 //=================================================================================
218 // function : ClickOnApply()
219 // purpose  :
220 //=================================================================================
221 void SMESHGUI_RemoveNodesDlg::ClickOnApply()
222 {
223   if (mySMESHGUI->isActiveStudyLocked())
224     return;
225
226   if (myNbOkNodes) {
227     QStringList aListId = myEditCurrentArgument->text().split(" ", QString::SkipEmptyParts);
228     SMESH::long_array_var anArrayOfIdeces = new SMESH::long_array;
229     anArrayOfIdeces->length(aListId.count());
230     for (int i = 0; i < aListId.count(); i++)
231       anArrayOfIdeces[i] = aListId[ i ].toInt();
232
233     bool aResult = false;
234     try {
235       SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
236       aResult = aMeshEditor->RemoveNodes(anArrayOfIdeces.inout());
237     } catch (const SALOME::SALOME_Exception& S_ex) {
238       SalomeApp_Tools::QtCatchCorbaException(S_ex);
239       myEditCurrentArgument->clear();
240     } catch (...){
241       myEditCurrentArgument->clear();
242     }
243
244     if (aResult) {
245       myEditCurrentArgument->clear();
246       mySelector->ClearIndex();
247       SMESH::UpdateView();
248     }
249
250     SMESH::SetPointRepresentation(true);
251   }
252 }
253
254 //=================================================================================
255 // function : ClickOnOk()
256 // purpose  :
257 //=================================================================================
258 void SMESHGUI_RemoveNodesDlg::ClickOnOk()
259 {
260   ClickOnApply();
261   ClickOnCancel();
262 }
263
264 //=================================================================================
265 // function : ClickOnCancel()
266 // purpose  :
267 //=================================================================================
268 void SMESHGUI_RemoveNodesDlg::ClickOnCancel()
269 {
270   //mySelectionMgr->clearSelected();
271   if (SMESH::GetCurrentVtkView()) {
272     SMESH::RemoveFilters(); // PAL6938 -- clean all mesh entity filters
273     SMESH::SetPointRepresentation(false);
274   }
275   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
276     aViewWindow->SetSelectionMode(ActorSelection);
277   disconnect(mySelectionMgr, 0, this, 0);
278   mySelectionMgr->clearFilters();
279   mySMESHGUI->ResetState();
280   reject();
281 }
282
283 //=================================================================================
284 // function : ClickOnHelp()
285 // purpose  :
286 //=================================================================================
287 void SMESHGUI_RemoveNodesDlg::ClickOnHelp()
288 {
289   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
290   if (app) 
291     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
292   else {
293     QString platform;
294 #ifdef WIN32
295     platform = "winapplication";
296 #else
297     platform = "application";
298 #endif
299     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
300                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
301                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
302                                                                  platform)).
303                              arg(myHelpFileName));
304   }
305 }
306
307 //=======================================================================
308 //function : onTextChange
309 //purpose  :
310 //=======================================================================
311 void SMESHGUI_RemoveNodesDlg::onTextChange(const QString& theNewText)
312 {
313   if (myBusy) return;
314   myBusy = true;
315
316   myNbOkNodes = 0;
317
318   buttonOk->setEnabled(false);
319   buttonApply->setEnabled(false);
320
321   // hilight entered nodes
322   if(myActor){
323     if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
324       Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
325            
326       TColStd_MapOfInteger newIndices;
327       
328       QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts);
329       for (int i = 0; i < aListId.count(); i++) {
330         if (const SMDS_MeshNode *aNode = aMesh->FindNode(aListId[i].toInt())) {
331           newIndices.Add(aNode->GetID());
332           myNbOkNodes++;
333         }
334       }
335
336       mySelector->AddOrRemoveIndex(anIO,newIndices,false);
337       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
338         aViewWindow->highlight(anIO,true,true);
339     }
340   }
341
342   if (myNbOkNodes) {
343     buttonOk->setEnabled(true);
344     buttonApply->setEnabled(true);
345   }
346
347   myBusy = false;
348 }
349
350 //=================================================================================
351 // function : SelectionIntoArgument()
352 // purpose  : Called when selection as changed or other case
353 //=================================================================================
354 void SMESHGUI_RemoveNodesDlg::SelectionIntoArgument()
355 {
356   if (myBusy) return;
357
358   // clear
359
360   myNbOkNodes = false;
361   myActor = 0;
362
363   myBusy = true;
364   myEditCurrentArgument->setText("");
365   myBusy = false;
366
367   if (!GroupButtons->isEnabled()) // inactive
368     return;
369
370   buttonOk->setEnabled(false);
371   buttonApply->setEnabled(false);
372
373   // get selected mesh
374   SALOME_ListIO aList;
375   mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
376
377   int nbSel = aList.Extent();
378   if (nbSel != 1)
379     return;
380
381   Handle(SALOME_InteractiveObject) anIO = aList.First();
382   myMesh = SMESH::GetMeshByIO(anIO);
383   if (myMesh->_is_nil())
384     return;
385
386   myActor = SMESH::FindActorByEntry(anIO->getEntry());
387   if (!myActor)
388     return;
389
390   // get selected nodes
391
392   QString aString = "";
393   int nbNodes = SMESH::GetNameOfSelectedNodes(mySelector,anIO,aString);
394   if(nbNodes < 1)
395     return;
396   myBusy = true;
397   myEditCurrentArgument->setText(aString);
398   myBusy = false;
399
400   // OK
401
402   myNbOkNodes = true;
403
404   buttonOk->setEnabled(true);
405   buttonApply->setEnabled(true);
406 }
407
408 //=================================================================================
409 // function : SetEditCurrentArgument()
410 // purpose  :
411 //=================================================================================
412 void SMESHGUI_RemoveNodesDlg::SetEditCurrentArgument()
413 {
414   QPushButton* send = (QPushButton*)sender();
415   switch (myConstructorId) {
416   case 0: /* default constructor */
417     {
418       if(send == SelectButtonC1A1) {
419         LineEditC1A1->setFocus();
420         myEditCurrentArgument = LineEditC1A1;
421       }
422       SelectionIntoArgument();
423       break;
424     }
425   }
426 }
427
428 //=================================================================================
429 // function : DeactivateActiveDialog()
430 // purpose  :
431 //=================================================================================
432 void SMESHGUI_RemoveNodesDlg::DeactivateActiveDialog()
433 {
434   if (GroupConstructors->isEnabled()) {
435     GroupConstructors->setEnabled(false);
436     GroupC1->setEnabled(false);
437     GroupButtons->setEnabled(false);
438     mySMESHGUI->ResetState(); // ??
439     mySMESHGUI->SetActiveDialogBox(0); // ??
440   }
441 }
442
443 //=================================================================================
444 // function : ActivateThisDialog()
445 // purpose  :
446 //=================================================================================
447 void SMESHGUI_RemoveNodesDlg::ActivateThisDialog()
448 {
449   /* Emit a signal to deactivate the active dialog */
450   mySMESHGUI->EmitSignalDeactivateDialog();
451
452   GroupConstructors->setEnabled(true);
453   GroupC1->setEnabled(true);
454   GroupButtons->setEnabled(true);
455
456   mySMESHGUI->SetActiveDialogBox((QDialog*)this); // ??
457
458   SMESH::SetPointRepresentation(true);
459   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
460     aViewWindow->SetSelectionMode(NodeSelection);
461
462   SelectionIntoArgument(); // ??
463 }
464
465 //=================================================================================
466 // function : enterEvent()
467 // purpose  :
468 //=================================================================================
469 void SMESHGUI_RemoveNodesDlg::enterEvent(QEvent*)
470 {
471   if (!GroupConstructors->isEnabled())
472     ActivateThisDialog();
473 }
474
475 //=================================================================================
476 // function : closeEvent()
477 // purpose  :
478 //=================================================================================
479 void SMESHGUI_RemoveNodesDlg::closeEvent(QCloseEvent*)
480 {
481   /* same than click on cancel button */
482   ClickOnCancel();
483 }
484
485 //=======================================================================
486 //function : hideEvent
487 //purpose  : caused by ESC key
488 //=======================================================================
489 void SMESHGUI_RemoveNodesDlg::hideEvent( QHideEvent* )
490 {
491   if (!isMinimized())
492     ClickOnCancel();
493 }
494
495 //=================================================================================
496 // function : keyPressEvent()
497 // purpose  :
498 //=================================================================================
499 void SMESHGUI_RemoveNodesDlg::keyPressEvent( QKeyEvent* e )
500 {
501   QDialog::keyPressEvent( e );
502   if ( e->isAccepted() )
503     return;
504
505   if ( e->key() == Qt::Key_F1 ) {
506     e->accept();
507     ClickOnHelp();
508   }
509 }
510
511 //=================================================================================
512 // function : setFilters()
513 // purpose  : SLOT. Called when "Filter" button pressed.
514 //=================================================================================
515 void SMESHGUI_RemoveNodesDlg::setFilters()
516 {
517   if(myMesh->_is_nil()) {
518     SUIT_MessageBox::critical(this,
519                               tr("SMESH_ERROR"),
520                               tr("NO_MESH_SELECTED"));
521    return;
522   }
523   if ( !myFilterDlg )
524     myFilterDlg = new SMESHGUI_FilterDlg( mySMESHGUI, SMESH::NODE );
525
526   myFilterDlg->SetSelection();
527   myFilterDlg->SetMesh( myMesh );
528   myFilterDlg->SetSourceWg( LineEditC1A1 );
529
530   myFilterDlg->show();
531 }