Salome HOME
Copyright update 2022
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_RemoveNodeReconnectionDlg.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 // File   : SMESHGUI_MakeNodeAtPointDlg.cxx
24 // Author : Edward AGAPOV, Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_RemoveNodeReconnectionDlg.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_IdValidator.h"
31 #include "SMESHGUI_MeshUtils.h"
32 #include "SMESHGUI_VTKUtils.h"
33 #include "SMESHGUI_MeshEditPreview.h"
34
35 #include <SMDS_Mesh.hxx>
36 #include <SMESH_Actor.h>
37 #include <SMESH_ActorUtils.h>
38 #include <SMESH_LogicalFilter.hxx>
39
40 // SALOME GUI includes
41 #include <LightApp_SelectionMgr.h>
42 #include <SALOME_ListIO.hxx>
43 #include <SUIT_Desktop.h>
44 #include <SVTK_ViewModel.h>
45 #include <SVTK_ViewWindow.h>
46 #include <SalomeApp_Tools.h>
47 #include <SalomeApp_TypeFilter.h>
48 #include <SUIT_ResourceMgr.h>
49 #include <SUIT_OverrideCursor.h>
50 #include <SUIT_MessageBox.h>
51
52 // Qt includes
53 #include <QApplication>
54 #include <QGroupBox>
55 #include <QGridLayout>
56 #include <QHBoxLayout>
57 #include <QVBoxLayout>
58 #include <QLineEdit>
59 #include <QPushButton>
60 #include <QLabel>
61 #include <QRadioButton>
62 #include <QCheckBox>
63 #include <QButtonGroup>
64
65 // VTK includes
66 #include <vtkProperty.h>
67
68 // IDL includes
69 #include <SALOMEconfig.h>
70 #include CORBA_SERVER_HEADER(SMESH_Mesh)
71 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
72
73 #define SPACING 6
74 #define MARGIN  11
75
76 //=======================================================================
77 /*!
78  * \brief Dialog to Remove a node with elements re-connection
79  */
80 //=======================================================================
81
82 SMESHGUI_RemoveNodeReconnectionDlg::SMESHGUI_RemoveNodeReconnectionDlg()
83   : SMESHGUI_Dialog( 0, false, true )
84 {
85   setWindowTitle(tr("CAPTION"));
86
87   QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
88   aDlgLay->setMargin(0);
89   aDlgLay->setSpacing(SPACING);
90   myMainFrame = createMainFrame(mainFrame());
91
92   aDlgLay->addWidget(myMainFrame);
93
94   aDlgLay->setStretchFactor(myMainFrame, 1);
95 }
96
97 //=======================================================================
98 // function : createMainFrame()
99 // purpose  : Create frame containing dialog's input fields
100 //=======================================================================
101
102 QWidget* SMESHGUI_RemoveNodeReconnectionDlg::createMainFrame (QWidget* theParent)
103 {
104   QWidget* aFrame = new QWidget(theParent);
105
106   // Node to remove
107
108   myNodeToMoveGrp = new QGroupBox(tr("NODE_2REMOVE"), aFrame);
109   myNodeToMoveGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
110   QLabel* idLabel = new QLabel(tr("NODE_2REMOVE_ID"), myNodeToMoveGrp);
111   myId = new QLineEdit(myNodeToMoveGrp);
112   myId->setValidator(new SMESHGUI_IdValidator(this, 1));
113
114   QGridLayout* myNodeToMoveGrpLayout = new QGridLayout(myNodeToMoveGrp);
115   myNodeToMoveGrpLayout->setSpacing(SPACING);
116   myNodeToMoveGrpLayout->setMargin(MARGIN);
117
118   myNodeToMoveGrpLayout->addWidget( idLabel, 0, 0 );
119   myNodeToMoveGrpLayout->addWidget( myId,    0, 2 );
120
121   // Preview
122
123   myPreviewChkBox = new QCheckBox( tr("PREVIEW"), aFrame);
124
125   QVBoxLayout* aLay = new QVBoxLayout(aFrame);
126   aLay->addWidget(myNodeToMoveGrp);
127   aLay->addWidget(myPreviewChkBox);
128
129   return aFrame;
130 }
131
132 //================================================================================
133 /*!
134  * \brief Constructor
135  */
136 //================================================================================
137
138 SMESHGUI_RemoveNodeReconnectionOp::SMESHGUI_RemoveNodeReconnectionOp()
139 {
140   mySimulation = 0;
141   mySMESHGUI = 0;
142   myDlg = new SMESHGUI_RemoveNodeReconnectionDlg;
143   myFilter = 0;
144   myHelpFileName = "removing_nodes_and_elements.html#removing-nodes-reconnect-anchor";
145
146   myNoPreview = false;
147
148   // connect signals and slots
149   connect(myDlg->myId,            SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview()));
150   connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)),              SLOT(redisplayPreview()));
151   connect(myDlg->myId,            SIGNAL (textChanged(const QString&)),SLOT(onTextChange(const QString&)));
152 }
153
154 //=======================================================================
155 // function : startOperation()
156 // purpose  : Init dialog fields, connect signals and slots, show dialog
157 //=======================================================================
158
159 void SMESHGUI_RemoveNodeReconnectionOp::startOperation()
160 {
161   myNoPreview = false;
162   myMeshActor = 0;
163
164   // init simulation with a current View
165   if ( mySimulation ) delete mySimulation;
166   mySMESHGUI = getSMESHGUI();
167   mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ) );
168   connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
169   connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
170   vtkProperty* aProp = vtkProperty::New();
171   aProp->SetRepresentationToWireframe();
172   aProp->SetColor(250, 0, 250);
173   aProp->SetPointSize(5);
174   aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1);
175   mySimulation->GetActor()->SetProperty(aProp);
176   aProp->Delete();
177
178   // SalomeApp_TypeFilter depends on a current study
179   if ( myFilter ) delete myFilter;
180   // QList<SUIT_SelectionFilter*> filters;
181   // filters.append( new SalomeApp_TypeFilter((SalomeApp_Study*)study(), "SMESH" ));
182   // myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
183
184   // IPAL19360
185   SMESHGUI_SelectionOp::startOperation(); // this method should be called only after filter creation
186   myDlg->myId->setText("");
187
188   myDlg->show();
189
190   onSelectionDone(); // init myMeshActor
191 }
192
193 //================================================================================
194 /*!
195  * \brief Stops operation
196  */
197 //================================================================================
198
199 void SMESHGUI_RemoveNodeReconnectionOp::stopOperation()
200 {
201   myNoPreview = true;
202   if ( mySimulation )
203   {
204     mySimulation->SetVisibility(false);
205     delete mySimulation;
206     mySimulation = 0;
207   }
208   if ( myMeshActor ) {
209     myMeshActor = 0;
210   }
211   SMESH::SetPointRepresentation( false );
212   SMESH::RepaintCurrentView();
213
214   disconnect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
215   disconnect(mySMESHGUI, SIGNAL (SignalCloseView()),            this, SLOT(onCloseView()));
216   //selectionMgr()->removeFilter( myFilter );
217   SMESHGUI_SelectionOp::stopOperation();
218 }
219
220 //================================================================================
221 /*!
222  * \brief perform it's intention action: move or create a node
223  */
224 //================================================================================
225
226 bool SMESHGUI_RemoveNodeReconnectionOp::onApply()
227 {
228   if( SMESHGUI::isStudyLocked() )
229     return false;
230
231   if ( !myMeshActor ) {
232     SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ), tr("INVALID_MESH") );
233     dlg()->show();
234     return false;
235   }
236
237   QString msg;
238   if ( !isValid( msg ) ) { // node id is invalid
239     if ( !msg.isEmpty() )
240       SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ), tr("INVALID_ID") );
241     dlg()->show();
242     return false;
243   }
244
245   try {
246     SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO( myMeshActor->getIO() );
247     if ( aMesh->_is_nil() )
248     {
249       SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"), tr("SMESHG_NO_MESH") );
250       return true;
251     }
252     SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
253     if ( aMeshEditor->_is_nil() )
254       return true;
255
256     bool ok;
257     int anId = myDlg->myId->text().toInt( &ok );
258     myDlg->myId->setText( "" );
259
260     aMeshEditor->RemoveNodeWithReconnection( anId );
261
262     SALOME_ListIO aList;
263     selectionMgr()->setSelectedObjects(aList,false);
264     aList.Append( myMeshActor->getIO() );
265     selectionMgr()->setSelectedObjects(aList,false);
266     SMESH::UpdateView();
267     SMESHGUI::Modified();
268
269   }
270   catch (const SALOME::SALOME_Exception& S_ex) {
271     SalomeApp_Tools::QtCatchCorbaException(S_ex);
272   }
273   catch (...) {
274   }
275
276   return true;
277 }
278
279 //================================================================================
280 /*!
281  * \brief Check selected node id validity
282  */
283 //================================================================================
284
285 bool SMESHGUI_RemoveNodeReconnectionOp::isValid( QString& msg )
286 {
287   bool ok = true;
288   if ( myMeshActor )
289   {
290     ok = false;
291     int id = myDlg->myId->text().toInt();
292     if ( id > 0 )
293       if ( SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh() )
294         ok = aMesh->FindNode( id );
295     if ( !ok )
296       msg += tr("INVALID_ID") + "\n";
297   }
298
299   return ok;
300 }
301
302 //================================================================================
303 /*!
304  * \brief SLOT called when selection changed
305  */
306 //================================================================================
307
308 void SMESHGUI_RemoveNodeReconnectionOp::onSelectionDone()
309 {
310   if ( !myDlg->isVisible() || !myDlg->isEnabled() )
311     return;
312
313   myDlg->myId->setText("");
314   myNoPreview = true;
315   try
316   {
317     SALOME_ListIO aList;
318     selectionMgr()->selectedObjects( aList, SVTK_Viewer::Type() );
319     if ( aList.Extent() != 1)
320       return;
321     Handle(SALOME_InteractiveObject) anIO = aList.First();
322     myMeshActor = SMESH::FindActorByEntry( anIO->getEntry() );
323
324     QString aString;
325     int nbElems = SMESH::GetNameOfSelectedElements( selector(), anIO, aString );
326     if ( nbElems == 1 )
327       myDlg->myId->setText( aString );
328
329   } catch (...) {
330   }
331
332   myNoPreview = false;
333   redisplayPreview();
334 }
335
336 //================================================================================
337 /*!
338  * \brief update preview
339  */
340 //================================================================================
341
342 void SMESHGUI_RemoveNodeReconnectionOp::redisplayPreview()
343 {
344   if ( myNoPreview )
345     return;
346   myNoPreview = true;
347
348   if ( !myMeshActor )
349     onSelectionDone();
350
351   SMESH::MeshPreviewStruct_var aMeshPreviewStruct;
352
353   QString msg;
354   if ( myMeshActor && isValid( msg ) && myDlg->myPreviewChkBox->isChecked() )
355     try {
356       SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO( myMeshActor->getIO() );
357       if ( !aMesh->_is_nil() )
358       {
359         SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer();
360         if (!aPreviewer->_is_nil())
361         {
362           int anId = myDlg->myId->text().toInt();
363           aPreviewer->RemoveNodeWithReconnection( anId );
364           aMeshPreviewStruct = aPreviewer->GetPreviewData();
365         }
366       }
367     }
368     catch (...) {
369     }
370
371   if (!mySimulation)
372     mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
373
374   // display data
375   if ( & aMeshPreviewStruct.in() )
376   {
377     mySimulation->SetData( aMeshPreviewStruct.in() );
378   }
379   else
380   {
381     mySimulation->SetVisibility( false );
382   }
383
384   myNoPreview = false;
385 }
386
387 //=================================================================================
388 /*!
389  * \brief SLOT called when the viewer opened
390  */
391 //=================================================================================
392
393 void SMESHGUI_RemoveNodeReconnectionOp::onOpenView()
394 {
395   if ( mySimulation )
396   {
397     mySimulation->SetVisibility( false );
398     SMESH::SetPointRepresentation( false );
399   }
400   else
401   {
402     mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
403   }
404 }
405
406 //=================================================================================
407 /*!
408  * \brief SLOT called when the viewer closed
409  */
410 //=================================================================================
411
412 void SMESHGUI_RemoveNodeReconnectionOp::onCloseView()
413 {
414   delete mySimulation;
415   mySimulation = 0;
416 }
417
418 //================================================================================
419 /*!
420  * \brief SLOT called when the node id is manually changed
421  */
422 //================================================================================
423
424 void SMESHGUI_RemoveNodeReconnectionOp::onTextChange( const QString& theText )
425 {
426   if( myMeshActor )
427   {
428     if( SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh() )
429     {
430       Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO();
431       SALOME_ListIO aList;
432       aList.Append( anIO );
433       selectionMgr()->setSelectedObjects( aList, false );
434
435       if ( const SMDS_MeshNode* aNode = aMesh->FindNode( theText.toInt() ))
436       {
437         SVTK_TVtkIDsMap aListInd;
438         aListInd.Add( FromSmIdType<int>( aNode->GetID()) );
439         selector()->AddOrRemoveIndex( anIO, aListInd, false );
440         if( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) )
441           aViewWindow->highlight( anIO, true, true );
442       }
443     }
444   }
445 }
446
447 //================================================================================
448 /*!
449  * \brief Activate Node selection
450  */
451 //================================================================================
452
453 void SMESHGUI_RemoveNodeReconnectionOp::activateSelection()
454 {
455   selectionMgr()->clearFilters();
456   SMESH::SetPointRepresentation( true );
457   //selectionMgr()->installFilter( myFilter );
458   setSelectionMode( NodeSelection );
459 }
460
461 //================================================================================
462 /*!
463  * \brief Destructor
464  */
465 //================================================================================
466
467 SMESHGUI_RemoveNodeReconnectionOp::~SMESHGUI_RemoveNodeReconnectionOp()
468 {
469   if ( myDlg )        delete myDlg;
470   if ( mySimulation ) delete mySimulation;
471   if ( myFilter )     delete myFilter;
472 }
473
474 //================================================================================
475 /*!
476  * \brief Gets dialog of this operation
477  * \retval LightApp_Dialog* - pointer to dialog of this operation
478  */
479 //================================================================================
480
481 LightApp_Dialog* SMESHGUI_RemoveNodeReconnectionOp::dlg() const
482 {
483   return myDlg;
484 }
485