Salome HOME
[Bug PAL7444] display mesh takes a lot of more memory in 2.1.0 than in 2.0.0.
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MoveNodesDlg.cxx
1 //  SMESH SMESHGUI : GUI for SMESH component
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SMESHGUI_MoveNodesDlg.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SMESH
27 //  $Header$
28
29 #include "SMESHGUI_MoveNodesDlg.h"
30
31 #include "SMESHGUI.h"
32 #include "SMESHGUI_SpinBox.h"
33 #include "SMESHGUI_IdValidator.h"
34
35 #include "SMESHGUI_Utils.h"
36 #include "SMESHGUI_VTKUtils.h"
37 #include "SMESHGUI_MeshUtils.h"
38
39 #include "SMESH_Actor.h"
40 #include "SMDS_Mesh.hxx"
41 #include "SMDS_MeshNode.hxx"
42
43 #include "SALOME_Selection.h"
44 #include "VTKViewer_ViewFrame.h"
45 #include "QAD_Desktop.h"
46 #include "QAD_RightFrame.h"
47 #include "QAD_MessageBox.h"
48
49 #include "utilities.h"
50
51 #include <vtkCell.h>
52 #include <vtkIdList.h>
53 #include <vtkIntArray.h>
54 #include <vtkCellArray.h>
55 #include <vtkUnsignedCharArray.h>
56 #include <vtkUnstructuredGrid.h>
57 #include <vtkDataSetMapper.h>
58
59 #include <qgroupbox.h>
60 #include <qlabel.h>
61 #include <qlineedit.h>
62 #include <qpushbutton.h>
63 #include <qradiobutton.h>
64 #include <qlayout.h>
65 #include <qpixmap.h>
66 #include <qmessagebox.h>
67 #include <qbuttongroup.h>
68
69 // IDL Headers
70 #include <SALOMEconfig.h>
71 #include CORBA_SERVER_HEADER(SMESH_Mesh)
72
73 #define MARGIN  10
74 #define SPACING 5
75
76
77 //=================================================================================
78 // class    : SMESHGUI_MoveNodesDlg()
79 // purpose  : 
80 //=================================================================================
81 SMESHGUI_MoveNodesDlg::SMESHGUI_MoveNodesDlg( QWidget*          theParent,
82                                               SALOME_Selection* theSelection,
83                                               const char*       theName )
84
85 : QDialog( theParent, theName, false,
86            WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu )
87 {
88   myPreviewActor = 0;
89   myBusy = false;
90   mySelection = 0;
91   
92   setCaption( tr( "CAPTION" ) );
93
94   QVBoxLayout* aDlgLay = new QVBoxLayout( this, MARGIN, SPACING );
95
96   QFrame* aMainFrame = createMainFrame  ( this );
97   QFrame* aBtnFrame  = createButtonFrame( this );
98
99   aDlgLay->addWidget( aMainFrame );
100   aDlgLay->addWidget( aBtnFrame );
101
102   aDlgLay->setStretchFactor( aMainFrame, 1 );
103
104   Init( theSelection ) ;
105 }
106
107 //=======================================================================
108 // name    : SMESHGUI_MoveNodesDlg::createButtonFrame
109 // Purpose : Create frame containing buttons
110 //=======================================================================
111 QFrame* SMESHGUI_MoveNodesDlg::createButtonFrame( QWidget* theParent )
112 {
113   QFrame* aFrame = new QFrame( theParent );
114   aFrame->setFrameStyle( QFrame::Box | QFrame::Sunken );
115
116   myOkBtn     = new QPushButton( tr( "SMESH_BUT_OK"    ), aFrame );
117   myApplyBtn  = new QPushButton( tr( "SMESH_BUT_APPLY" ), aFrame );
118   myCloseBtn  = new QPushButton( tr( "SMESH_BUT_CLOSE" ), aFrame );
119
120   QSpacerItem* aSpacer = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
121
122   QHBoxLayout* aLay = new QHBoxLayout( aFrame, MARGIN, SPACING );
123
124   aLay->addWidget( myOkBtn );
125   aLay->addWidget( myApplyBtn );
126   aLay->addItem( aSpacer);
127   aLay->addWidget( myCloseBtn );
128
129   connect( myOkBtn,    SIGNAL( clicked() ), SLOT( onOk() ) );
130   connect( myCloseBtn, SIGNAL( clicked() ), SLOT( onClose() ) ) ;
131   connect( myApplyBtn, SIGNAL( clicked() ), SLOT( onApply() ) );
132
133   return aFrame;
134 }
135
136 //=======================================================================
137 // name    : SMESHGUI_MoveNodesDlg::createMainFrame
138 // Purpose : Create frame containing dialog's input fields
139 //=======================================================================
140 QFrame* SMESHGUI_MoveNodesDlg::createMainFrame( QWidget* theParent )
141 {
142   QFrame* aFrame = new QFrame( theParent );
143
144   QPixmap iconMoveNode(
145     QAD_Desktop::getResourceManager()->loadPixmap( "SMESH",tr( "ICON_DLG_MOVE_NODE" ) ) );
146   QPixmap iconSelect(
147     QAD_Desktop::getResourceManager()->loadPixmap( "SMESH",tr( "ICON_SELECT" ) ) );
148
149   QButtonGroup* aPixGrp = new QButtonGroup( 1, Qt::Vertical, tr( "MESH_NODE" ), aFrame );
150   aPixGrp->setExclusive( TRUE );
151   QRadioButton* aRBut = new QRadioButton( aPixGrp );
152   aRBut->setPixmap( iconMoveNode );
153   aRBut->setChecked( TRUE );
154
155   QGroupBox* anIdGrp = new QGroupBox( 1, Qt::Vertical, tr( "SMESH_MOVE" ), aFrame );
156   new QLabel( tr( "NODE_ID" ), anIdGrp );
157   ( new QPushButton( anIdGrp ) )->setPixmap( iconSelect );
158   myId = new QLineEdit( anIdGrp );
159   myId->setValidator( new SMESHGUI_IdValidator( this, "validator", 1 ));
160
161   QGroupBox* aCoordGrp = new QGroupBox( 1, Qt::Vertical, tr( "SMESH_COORDINATES" ), aFrame );
162   new QLabel( tr( "SMESH_X" ), aCoordGrp );
163   myX = new SMESHGUI_SpinBox( aCoordGrp );
164   new QLabel( tr( "SMESH_Y" ), aCoordGrp );
165   myY = new SMESHGUI_SpinBox( aCoordGrp );
166   new QLabel( tr( "SMESH_Z" ), aCoordGrp );
167   myZ = new SMESHGUI_SpinBox( aCoordGrp );
168
169   myX->RangeStepAndValidator( -999999.999, +999999.999, 25.0, 3 );
170   myY->RangeStepAndValidator( -999999.999, +999999.999, 25.0, 3 );
171   myZ->RangeStepAndValidator( -999999.999, +999999.999, 25.0, 3 );  
172
173   QVBoxLayout* aLay = new QVBoxLayout( aFrame );
174   aLay->addWidget( aPixGrp );
175   aLay->addWidget( anIdGrp );
176   aLay->addWidget( aCoordGrp );
177
178   // connect signale and slots
179   connect( myX, SIGNAL ( valueChanged( double) ), this, SLOT( redisplayPreview() ) );
180   connect( myY, SIGNAL ( valueChanged( double) ), this, SLOT( redisplayPreview() ) );
181   connect( myZ, SIGNAL ( valueChanged( double) ), this, SLOT( redisplayPreview() ) );
182   connect( myId, SIGNAL( textChanged(const QString&) ), SLOT( onTextChange(const QString&) ));
183
184   return aFrame;
185 }
186
187 //=======================================================================
188 // name    : SMESHGUI_MoveNodesDlg::~SMESHGUI_MoveNodesDlg
189 // Purpose :
190 //=======================================================================
191 SMESHGUI_MoveNodesDlg::~SMESHGUI_MoveNodesDlg()
192 {
193   erasePreview();
194 }
195
196 //=======================================================================
197 // name    : SMESHGUI_MoveNodesDlg::Init
198 // Purpose : Init dialog fields
199 //=======================================================================
200 void SMESHGUI_MoveNodesDlg::Init( SALOME_Selection* theSelection )
201 {
202   myPreviewActor = 0;
203   myMeshActor = 0;
204   myBusy = false;
205   mySelection = theSelection;
206
207   SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI();
208   aSMESHGUI->SetActiveDialogBox( ( QDialog* )this ) ;
209
210   // selection and SMESHGUI
211   connect( mySelection, SIGNAL( currentSelectionChanged() ), SLOT( onSelectionDone() ) );
212   connect( aSMESHGUI, SIGNAL( SignalDeactivateActiveDialog() ), SLOT( onDeactivate() ) );
213   connect( aSMESHGUI, SIGNAL( SignalCloseAllDialogs() ), SLOT( onClose() ) );
214
215   reset();
216   setEnabled( true );
217
218   int x, y ;
219   aSMESHGUI->DefineDlgPosition( this, x, y );
220   this->move( x, y );
221   this->show();
222
223   // set selection mode
224   SMESH::SetPointRepresentation(true);
225   QAD_Application::getDesktop()->SetSelectionMode( NodeSelection, true );
226   onSelectionDone();
227 }
228
229 //=======================================================================
230 // name    : SMESHGUI_MoveNodesDlg::isValid
231 // Purpose : Verify validity of entry information
232 //=======================================================================
233 bool SMESHGUI_MoveNodesDlg::isValid( const bool theMess ) const
234 {
235   if ( myId->text().isEmpty() )
236   {
237     if ( theMess )
238       QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
239         tr( "SMESH_WARNING" ), tr( "NODE_ID_IS_NOT_DEFINED" ), QMessageBox::Ok );
240     return false;
241   }
242   return true;
243 }
244
245 //=======================================================================
246 // name    : SMESHGUI_MoveNodesDlg::reset
247 // Purpose : Reset the dialog state
248 //=======================================================================
249 void SMESHGUI_MoveNodesDlg::reset()
250 {
251   myId->clear();
252   myX->SetValue( 0 );
253   myY->SetValue( 0 );
254   myZ->SetValue( 0 );
255   redisplayPreview();
256   updateButtons();
257 }
258
259 //=======================================================================
260 // name    : SMESHGUI_MoveNodesDlg::nApply
261 // Purpose : SLOT called when "Apply" button pressed.
262 //=======================================================================
263 bool SMESHGUI_MoveNodesDlg::onApply()
264 {
265   if (SMESHGUI::GetSMESHGUI()->ActiveStudyLocked())
266     return false;
267
268   if ( !isValid( true ) )
269     return false;
270
271   SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO( myMeshActor->getIO() );
272   if(aMesh->_is_nil() )
273   {
274     QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
275     tr( "SMESH_ERROR" ), tr( "SMESHG_NO_MESH" ), QMessageBox::Ok );
276     return false;
277   }
278
279   SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
280   if ( aMeshEditor->_is_nil() )
281     return false;
282
283   int anId = myId->text().toInt();
284   bool aResult = false;
285   try
286   {
287     aResult = aMeshEditor->MoveNode( anId, myX->GetValue(), myY->GetValue(), myZ->GetValue() );
288   }
289   catch( ... )
290   {
291   }
292
293   if ( aResult )
294   {
295     Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO();
296     mySelection->ClearIObjects();
297     SMESH::UpdateView();
298     mySelection->AddIObject( anIO, false );
299     reset();
300   }
301
302   return aResult;
303 }
304
305
306 //=======================================================================
307 // name    : SMESHGUI_MoveNodesDlg::onOk
308 // Purpose : SLOT called when "Ok" button pressed.
309 //=======================================================================
310 void SMESHGUI_MoveNodesDlg::onOk()
311 {
312   if ( onApply() )
313     onClose();
314 }
315
316
317 //=======================================================================
318 // name    : SMESHGUI_MoveNodesDlg::onClose
319 // Purpose : SLOT called when "Close" button pressed. Close dialog
320 //=======================================================================
321 void SMESHGUI_MoveNodesDlg::onClose()
322 {
323   mySelection->ClearIObjects();
324   SMESH::SetPointRepresentation(false);
325   QAD_Application::getDesktop()->SetSelectionMode( ActorSelection );
326   disconnect( mySelection, 0, this, 0 );
327   disconnect( SMESHGUI::GetSMESHGUI(), 0, this, 0 );
328   SMESHGUI::GetSMESHGUI()->ResetState();
329   reject();
330 }
331
332
333
334 //=======================================================================
335 //function : onTextChange
336 //purpose  : 
337 //=======================================================================
338
339 void SMESHGUI_MoveNodesDlg::onTextChange(const QString& theNewText)
340 {
341   if ( myBusy ) return;
342
343   myOkBtn->setEnabled( false );
344   myApplyBtn->setEnabled( false );
345   erasePreview();
346
347   // select entered node
348   SMDS_Mesh* aMesh = 0;
349   if ( myMeshActor )
350     aMesh = myMeshActor->GetObject()->GetMesh();
351   if ( aMesh ) {
352
353     myBusy = true;
354     mySelection->ClearIObjects();
355     mySelection->AddIObject( myMeshActor->getIO() );
356     myBusy = false;
357
358     const SMDS_MeshElement * e = aMesh->FindElement( theNewText.toInt() );
359     if ( e )
360       mySelection->AddOrRemoveIndex (myMeshActor->getIO(), e->GetID(), true);
361   }
362 }
363
364 //=======================================================================
365 // name    : SMESHGUI_MoveNodesDlg::onSelectionDone
366 // Purpose : SLOT called when selection changed
367 //=======================================================================
368 void SMESHGUI_MoveNodesDlg::onSelectionDone()
369 {
370   if ( myBusy ) return;
371   myMeshActor = 0;
372
373   if ( mySelection->IObjectCount() == 1 ) {
374     myMeshActor = SMESH::FindActorByEntry(mySelection->firstIObject()->getEntry());
375     if ( myMeshActor )
376     {
377       QString aText;
378       if ( SMESH::GetNameOfSelectedNodes( mySelection, aText ) == 1 ) {
379         if(SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh()) {
380           if(const SMDS_MeshNode* aNode = aMesh->FindNode(aText.toInt())) {
381             myBusy = true;
382             myId->setText( aText );
383             myX->SetValue( aNode->X() );
384             myY->SetValue( aNode->Y() );
385             myZ->SetValue( aNode->Z() );
386             myBusy = false;
387             erasePreview(); // avoid overlapping of a selection and a preview
388             updateButtons();
389             return;
390           }
391         }
392       }
393     }
394   }
395
396   reset();
397 }
398
399
400 //=======================================================================
401 // name    : SMESHGUI_MoveNodesDlg::onDeactivate
402 // Purpose : SLOT called when dialog must be deativated
403 //=======================================================================
404 void SMESHGUI_MoveNodesDlg::onDeactivate()
405 {
406   setEnabled( false );
407   erasePreview();
408 }
409
410
411 //=======================================================================
412 // name    : SMESHGUI_MoveNodesDlg::enterEvent
413 // Purpose : Event filter
414 //=======================================================================
415 void SMESHGUI_MoveNodesDlg::enterEvent( QEvent* )
416 {
417   if ( !isEnabled() )
418   {
419     SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
420
421     // set selection mode
422     SMESH::SetPointRepresentation(true);
423     QAD_Application::getDesktop()->SetSelectionMode( NodeSelection, true );
424
425     redisplayPreview();
426   
427     setEnabled( true );
428   }
429 }
430
431
432 //=================================================================================
433 // function : closeEvent()
434 // purpose  :
435 //=================================================================================
436 void SMESHGUI_MoveNodesDlg::closeEvent( QCloseEvent* e )
437 {
438   onClose() ;                  
439   SMESH::GetCurrentVtkView()->Repaint();
440 }
441
442 //=======================================================================
443 //function : hideEvent
444 //purpose  : may be caused by ESC key
445 //=======================================================================
446
447 void SMESHGUI_MoveNodesDlg::hideEvent ( QHideEvent * e )
448 {
449   if ( !isMinimized() )
450     onClose();
451 }
452
453 //=======================================================================
454 // name    : SMESHGUI_MoveNodesDlg::updateButtons
455 // Purpose : Update buttons state
456 //=======================================================================
457 void SMESHGUI_MoveNodesDlg::updateButtons()
458 {
459   bool isEnabled = isValid( false );
460   myOkBtn->setEnabled( isEnabled );
461   myApplyBtn->setEnabled( isEnabled );
462 }
463
464 //=======================================================================
465 // name    : SMESHGUI_MoveNodesDlg::erasePreview
466 // Purpose : Erase preview
467 //=======================================================================
468 void  SMESHGUI_MoveNodesDlg::erasePreview()
469 {
470   if ( myPreviewActor == 0 )
471     return;
472
473   if ( VTKViewer_ViewFrame* vf = SMESH::GetCurrentVtkView() )
474     vf->RemoveActor(myPreviewActor);
475   myPreviewActor->Delete();
476   myPreviewActor = 0;
477   SMESH::GetCurrentVtkView()->Repaint();
478 }
479
480 //=======================================================================
481 // name    : SMESHGUI_MoveNodesDlg::redisplayPreview
482 // Purpose : Redisplay preview
483 //=======================================================================
484 void SMESHGUI_MoveNodesDlg::redisplayPreview()
485 {
486   if ( myBusy )
487     return;
488   
489   if ( myPreviewActor != 0 )
490     erasePreview();
491   
492   if ( !isValid( false ) )
493     return;
494
495   vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
496   
497   vtkPoints* aPoints = vtkPoints::New();
498   aPoints->SetNumberOfPoints( 1 );
499   aPoints->SetPoint( 0, myX->GetValue(), myY->GetValue(), myZ->GetValue() );
500
501   // Create cells
502   
503   vtkIdList *anIdList = vtkIdList::New();
504   anIdList->SetNumberOfIds( 1 );
505
506   vtkCellArray *aCells = vtkCellArray::New();
507   aCells->Allocate( 2, 0 );
508
509   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
510   aCellTypesArray->SetNumberOfComponents( 1 );
511   aCellTypesArray->Allocate( 1 );
512
513   anIdList->SetId( 0, 0 );
514   aCells->InsertNextCell( anIdList );
515   aCellTypesArray->InsertNextValue( VTK_VERTEX );
516
517   vtkIntArray* aCellLocationsArray = vtkIntArray::New();
518   aCellLocationsArray->SetNumberOfComponents( 1 );
519   aCellLocationsArray->SetNumberOfTuples( 1 );
520
521   aCells->InitTraversal();
522   vtkIdType npts;
523   aCellLocationsArray->SetValue( 0, aCells->GetTraversalLocation( npts ) );
524
525   aGrid->SetCells( aCellTypesArray, aCellLocationsArray, aCells );
526
527   aGrid->SetPoints( aPoints );
528   aGrid->SetCells( aCellTypesArray, aCellLocationsArray,aCells );
529
530   // Create and display actor
531   vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
532   aMapper->SetInput( aGrid );
533
534   myPreviewActor = SALOME_Actor::New();
535   myPreviewActor->PickableOff();
536   myPreviewActor->SetMapper( aMapper );
537
538   vtkProperty* aProp = vtkProperty::New();
539   aProp->SetRepresentationToWireframe();
540   aProp->SetColor( 250, 0, 250 );
541   aProp->SetPointSize( 5 );
542   myPreviewActor->SetProperty( aProp );
543
544   SMESH::GetCurrentVtkView()->AddActor( myPreviewActor );
545   SMESH::GetCurrentVtkView()->Repaint();
546
547   aProp->Delete();
548   aCellLocationsArray->Delete();
549   aCellTypesArray->Delete();
550   aCells->Delete();
551   anIdList->Delete(); 
552   aPoints->Delete();
553   aGrid->Delete();
554 }
555