1 // SMESH SMESHGUI : GUI for SMESH component
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // File : SMESHGUI_MakeNodeAtPointDlg.cxx
25 // Author : Edward AGAPOV
28 #include "SMESHGUI_MakeNodeAtPointDlg.h"
31 #include "SMESHGUI_GEOMGenUtils.h"
32 #include "SMESHGUI_IdValidator.h"
33 #include "SMESHGUI_MeshUtils.h"
34 #include "SMESHGUI_Utils.h"
35 #include "SMESHGUI_VTKUtils.h"
36 #include "SMESHGUI_SpinBox.h"
37 #include "SMESHGUI_MeshEditPreview.h"
39 #include "SMDS_Mesh.hxx"
40 #include "SMDS_MeshNode.hxx"
41 #include "SMESH_Actor.h"
42 #include "SMESH_ActorUtils.h"
45 #include "GeometryGUI.h"
47 #include "LightApp_DataOwner.h"
48 #include "LightApp_SelectionMgr.h"
49 #include "SALOMEDSClient_SObject.hxx"
50 #include "SALOME_ListIO.hxx"
51 #include "SUIT_Desktop.h"
52 #include "SVTK_Selector.h"
53 #include "SVTK_ViewWindow.h"
54 #include "SVTK_ViewModel.h"
55 #include "SalomeApp_Tools.h"
56 #include "SUIT_ResourceMgr.h"
57 #include "SUIT_OverrideCursor.h"
58 #include "SUIT_MessageBox.h"
61 #include <TColStd_MapOfInteger.hxx>
62 #include <TopoDS_Shape.hxx>
63 #include <TopExp_Explorer.hxx>
68 #include <qlineedit.h>
69 #include <qpushbutton.h>
71 #include <qradiobutton.h>
72 #include <qbuttongroup.h>
73 #include <qapplication.h>
74 #include <qstringlist.h>
75 #include <qcheckbox.h>
76 #include <qmessagebox.h>
78 #include <vtkProperty.h>
81 #include <SALOMEconfig.h>
82 #include CORBA_SERVER_HEADER(SMESH_Mesh)
83 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
89 * \brief Dialog to publish a sub-shape of the mesh main shape
90 * by selecting mesh elements
92 SMESHGUI_MakeNodeAtPointDlg::SMESHGUI_MakeNodeAtPointDlg()
93 : SMESHGUI_Dialog( 0, false, true )
95 setCaption(tr("CAPTION"));
97 QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame(), MARGIN, SPACING);
99 QFrame* aMainFrame = createMainFrame (mainFrame());
101 aDlgLay->addWidget(aMainFrame);
103 aDlgLay->setStretchFactor(aMainFrame, 1);
106 //=======================================================================
107 // function : createMainFrame()
108 // purpose : Create frame containing dialog's input fields
109 //=======================================================================
110 QFrame* SMESHGUI_MakeNodeAtPointDlg::createMainFrame (QWidget* theParent)
112 QFrame* aFrame = new QFrame(theParent);
114 SUIT_ResourceMgr* rm = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
115 QPixmap iconMoveNode (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_NODE")));
116 QPixmap iconSelect (rm->loadPixmap("SMESH", tr("ICON_SELECT")));
120 QButtonGroup* aPixGrp = new QButtonGroup(1, Qt::Vertical, tr("MESH_PASS_THROUGH_POINT"), aFrame);
121 aPixGrp->setExclusive(TRUE);
122 QRadioButton* aRBut = new QRadioButton(aPixGrp);
123 aRBut->setPixmap(iconMoveNode);
124 aRBut->setChecked(TRUE);
128 QGroupBox* aCoordGrp = new QGroupBox(1, Qt::Vertical, tr("SMESH_COORDINATES"), aFrame);
129 myCoordBtn = new QPushButton(aCoordGrp);
130 myCoordBtn->setPixmap(iconSelect);
131 myCoordBtn->setToggleButton(TRUE);
133 QLabel* aXLabel = new QLabel(tr("SMESH_X"), aCoordGrp);
134 aXLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
135 myX = new SMESHGUI_SpinBox(aCoordGrp);
137 QLabel* aYLabel = new QLabel(tr("SMESH_Y"), aCoordGrp);
138 aYLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs );
139 myY = new SMESHGUI_SpinBox(aCoordGrp);
141 QLabel* aZLabel = new QLabel(tr("SMESH_Z"), aCoordGrp);
142 aZLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs );
143 myZ = new SMESHGUI_SpinBox(aCoordGrp);
145 myX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3);
146 myY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3);
147 myZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3);
151 QButtonGroup* aMethodGrp = new QButtonGroup(1, Qt::Vertical, tr("METHOD"), aFrame);
152 aMethodGrp->setExclusive(TRUE);
153 myMoveRBtn = new QRadioButton(tr("MOVE_EXISTING_METHOD"), aMethodGrp);
154 myCreateRBtn = new QRadioButton(tr("CREATE_NEW_METHOD"), aMethodGrp);
158 myNodeToMoveGrp = new QGroupBox(tr("NODE_2MOVE"), aFrame, "anIdGrp");
160 QLabel* idLabel = new QLabel(tr("NODE_2MOVE_ID"), myNodeToMoveGrp, "idLabel");
161 myIdBtn = new QPushButton(myNodeToMoveGrp);
162 myIdBtn->setPixmap(iconSelect);
163 myIdBtn->setToggleButton(TRUE);
164 myId = new QLineEdit(myNodeToMoveGrp,"myId");
165 myId->setValidator(new SMESHGUI_IdValidator(this, "validator", 1));
166 myAutoSearchChkBox = new QCheckBox( tr("AUTO_SEARCH"), myNodeToMoveGrp, "myAutoSearchChkBox");
167 myPreviewChkBox = new QCheckBox( tr("PREVIEW"), myNodeToMoveGrp, "myPreviewChkBox");
169 myNodeToMoveGrp->setColumnLayout(0, Qt::Vertical);
170 myNodeToMoveGrp->layout()->setSpacing(0);
171 myNodeToMoveGrp->layout()->setMargin(0);
172 QGridLayout* myNodeToMoveGrpLayout = new QGridLayout(myNodeToMoveGrp->layout());
173 myNodeToMoveGrpLayout->setAlignment(Qt::AlignTop);
174 myNodeToMoveGrpLayout->setSpacing(SPACING);
175 myNodeToMoveGrpLayout->setMargin(MARGIN);
176 myNodeToMoveGrpLayout->addWidget( idLabel, 0, 0 );
177 myNodeToMoveGrpLayout->addWidget( myIdBtn, 0, 1 );
178 myNodeToMoveGrpLayout->addWidget( myId, 0, 2 );
179 myNodeToMoveGrpLayout->addMultiCellWidget( myAutoSearchChkBox, 1, 1, 0, 2 );
180 myNodeToMoveGrpLayout->addMultiCellWidget( myPreviewChkBox, 2, 2, 0, 2 );
182 QVBoxLayout* aLay = new QVBoxLayout(aFrame);
183 aLay->addWidget(aPixGrp);
184 aLay->addWidget(aCoordGrp);
185 aLay->addWidget(aMethodGrp);
186 aLay->addWidget(myNodeToMoveGrp);
188 connect(myCoordBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
189 connect(myMoveRBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
190 connect(myCreateRBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
191 connect(myIdBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
192 connect(myAutoSearchChkBox, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
194 myMoveRBtn->setChecked(TRUE);
195 myIdBtn->setOn(TRUE);
196 myAutoSearchChkBox->setChecked(TRUE);
201 //================================================================================
203 * \brief SLOT called when any button is toggled
204 * \param bool - on or off
206 //================================================================================
208 void SMESHGUI_MakeNodeAtPointDlg::ButtonToggled (bool on)
210 const QObject* aSender = sender();
212 if ( aSender == myCoordBtn ) // button to set coord by node selection
214 if ( myIdBtn->isEnabled() )
215 myIdBtn->setOn( !on );
217 else if ( aSender == myIdBtn ) // button to select a node to move
219 myCoordBtn->setOn( !on );
221 else if ( aSender == myMoveRBtn ) // move node method
223 myNodeToMoveGrp->setEnabled( TRUE );
225 else if ( aSender == myCreateRBtn ) // create node method
227 myNodeToMoveGrp->setEnabled( FALSE );
228 myCoordBtn->setOn( TRUE );
231 if ( aSender == myAutoSearchChkBox ) // automatic node search
235 myId->setReadOnly ( TRUE );
236 myIdBtn->setOn( FALSE );
237 myIdBtn->setEnabled( FALSE );
238 myCoordBtn->setOn( TRUE );
241 myId->setReadOnly ( FALSE );
242 myIdBtn->setEnabled( TRUE );
247 //================================================================================
251 //================================================================================
253 SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp()
256 myDlg = new SMESHGUI_MakeNodeAtPointDlg;
258 // connect signals and slots
259 connect(myDlg->myX, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
260 connect(myDlg->myY, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
261 connect(myDlg->myZ, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
262 connect(myDlg->myId,SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview()));
263 connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
264 connect(myDlg->myAutoSearchChkBox,SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
265 connect(myDlg->myMoveRBtn, SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
266 connect(myDlg->myCreateRBtn, SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
269 //=======================================================================
270 // function : startOperation()
271 // purpose : Init dialog fields, connect signals and slots, show dialog
272 //=======================================================================
273 void SMESHGUI_MakeNodeAtPointOp::startOperation()
278 // init simulation with a current View
279 if ( mySimulation ) delete mySimulation;
280 mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( getSMESHGUI() ));
281 vtkProperty* aProp = vtkProperty::New();
282 aProp->SetRepresentationToWireframe();
283 aProp->SetColor(250, 0, 250);
284 aProp->SetPointSize(5);
285 aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1);
286 mySimulation->GetActor()->SetProperty(aProp);
289 SMESHGUI_SelectionOp::startOperation();
291 activateSelection(); // set filters
293 myDlg->myX->SetValue(0);
294 myDlg->myY->SetValue(0);
295 myDlg->myZ->SetValue(0);
296 myDlg->myId->setText("");
299 onSelectionDone(); // init myMeshActor
302 // myMeshOldDisplayMode = myMeshActor->GetRepresentation();
303 // myMeshActor->SetRepresentation( VTK_WIREFRAME );
304 myMeshActor->SetPointRepresentation(true);
305 SMESH::RepaintCurrentView();
310 //================================================================================
312 * \brief Stops operation
314 //================================================================================
316 void SMESHGUI_MakeNodeAtPointOp::stopOperation()
319 mySimulation->SetVisibility(false);
321 // myMeshActor->SetRepresentation( myMeshOldDisplayMode );
322 myMeshActor->SetPointRepresentation(false);
323 SMESH::RepaintCurrentView();
326 SMESHGUI_SelectionOp::stopOperation();
329 //================================================================================
331 * \brief perform it's intention action: move or create a node
333 //================================================================================
335 bool SMESHGUI_MakeNodeAtPointOp::onApply()
337 if ( !myMeshActor ) {
338 SUIT_MessageBox::warn1( dlg(), tr( "SMESH_WRN_WARNING" ),
339 tr("INVALID_MESH"), tr( "SMESH_BUT_OK" ) );
344 if ( !isValid() ) { // node id is invalid
345 SUIT_MessageBox::warn1( dlg(), tr( "SMESH_WRN_WARNING" ),
346 tr("INVALID_ID"), tr( "SMESH_BUT_OK" ) );
353 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
354 if (aMesh->_is_nil()) {
355 QMessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"),
356 tr("SMESHG_NO_MESH"), QMessageBox::Ok);
359 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
360 if (aMeshEditor->_is_nil())
364 if ( myDlg->myCreateRBtn->isOn() )
366 aResult = aMeshEditor->AddNode(myDlg->myX->GetValue(),
367 myDlg->myY->GetValue(),
368 myDlg->myZ->GetValue());
372 int anId = myDlg->myId->text().toInt();
373 aResult = aMeshEditor->MoveClosestNodeToPoint(myDlg->myX->GetValue(),
374 myDlg->myY->GetValue(),
375 myDlg->myZ->GetValue(),
380 myDlg->myId->setText("");
383 aList.Append(myMeshActor->getIO());
384 selectionMgr()->setSelectedObjects(aList,false);
388 catch (const SALOME::SALOME_Exception& S_ex) {
389 SalomeApp_Tools::QtCatchCorbaException(S_ex);
397 //================================================================================
399 * \brief Check selected node id validity
401 //================================================================================
403 bool SMESHGUI_MakeNodeAtPointOp::isValid()
408 myDlg->myMoveRBtn->isOn() &&
409 !myDlg->myAutoSearchChkBox->isChecked() )
412 int id = myDlg->myId->text().toInt();
414 if (SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh())
415 ok = aMesh->FindNode( id );
420 //================================================================================
422 * \brief SLOT called when selection changed
424 //================================================================================
426 void SMESHGUI_MakeNodeAtPointOp::onSelectionDone()
428 if ( !myDlg->isShown() || !myDlg->isEnabled() )
432 selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type());
433 if (aList.Extent() != 1)
435 Handle(SALOME_InteractiveObject) anIO = aList.First();
436 SMESH_Actor* aMeshActor = SMESH::FindActorByEntry(anIO->getEntry());
440 myMeshActor = aMeshActor;
442 int nbElems = SMESH::GetNameOfSelectedElements(selector(),anIO, aString);
444 if (SMDS_Mesh* aMesh = aMeshActor->GetObject()->GetMesh()) {
445 if (const SMDS_MeshNode* aNode = aMesh->FindNode(aString.toInt())) {
447 if ( myDlg->myCoordBtn->isOn() ) { // set coord
448 myDlg->myX->SetValue(aNode->X());
449 myDlg->myY->SetValue(aNode->Y());
450 myDlg->myZ->SetValue(aNode->Z());
454 else if ( myDlg->myIdBtn->isOn() &&
455 myDlg->myIdBtn->isEnabled() ) { // set node to move
456 myDlg->myId->setText(aString);
467 //================================================================================
469 * \brief update preview
471 //================================================================================
473 void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
479 SMESH::MeshPreviewStruct_var aMeshPreviewStruct;
481 bool moveShown = false;
482 if ( myDlg->myMoveRBtn->isOn() && // Move method
485 const bool autoSearch = myDlg->myAutoSearchChkBox->isChecked();
486 const bool preview = myDlg->myPreviewChkBox->isChecked();
488 myDlg->myId->setText("");
489 if ( preview && ( autoSearch || isValid() ))
492 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
493 if (!aMesh->_is_nil()) {
494 SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer();
495 if (!aPreviewer->_is_nil())
497 SUIT_OverrideCursor aWaitCursor;
499 // find id and/or just compute preview
500 int anId = aPreviewer->MoveClosestNodeToPoint(myDlg->myX->GetValue(),
501 myDlg->myY->GetValue(),
502 myDlg->myZ->GetValue(),
503 myDlg->myId->text().toInt());
504 if ( autoSearch ) { // set found id
507 idTxt = idTxt.arg( anId );
510 myDlg->myId->setText( idTxt );
512 if ( preview ) { // fill preview data
513 aMeshPreviewStruct = aPreviewer->GetPreviewData();
514 moveShown = ( anId > 0 );
525 aMeshPreviewStruct = new SMESH::MeshPreviewStruct();
527 aMeshPreviewStruct->nodesXYZ.length(1);
528 aMeshPreviewStruct->nodesXYZ[0].x = myDlg->myX->GetValue();
529 aMeshPreviewStruct->nodesXYZ[0].y = myDlg->myY->GetValue();
530 aMeshPreviewStruct->nodesXYZ[0].z = myDlg->myZ->GetValue();
532 aMeshPreviewStruct->elementTypes.length(1);
533 aMeshPreviewStruct->elementTypes[0].SMDS_ElementType = SMESH::NODE;
534 aMeshPreviewStruct->elementTypes[0].isPoly = false;
535 aMeshPreviewStruct->elementTypes[0].nbNodesInElement = 1;
537 aMeshPreviewStruct->elementConnectivities.length(1);
538 aMeshPreviewStruct->elementConnectivities[0] = 0;
542 if ( aMeshPreviewStruct.operator->() )
544 mySimulation->SetData(aMeshPreviewStruct._retn());
548 mySimulation->SetVisibility(false);
554 //================================================================================
556 * \brief Activate Node selection
558 //================================================================================
560 void SMESHGUI_MakeNodeAtPointOp::activateSelection()
562 selectionMgr()->clearFilters();
563 SMESH::SetPointRepresentation(false);
564 setSelectionMode( NodeSelection );
567 //================================================================================
571 //================================================================================
573 SMESHGUI_MakeNodeAtPointOp::~SMESHGUI_MakeNodeAtPointOp()
580 //================================================================================
582 * \brief Gets dialog of this operation
583 * \retval LightApp_Dialog* - pointer to dialog of this operation
585 //================================================================================
587 LightApp_Dialog* SMESHGUI_MakeNodeAtPointOp::dlg() const