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"
60 #include <TColStd_MapOfInteger.hxx>
61 #include <TopoDS_Shape.hxx>
62 #include <TopExp_Explorer.hxx>
67 #include <qlineedit.h>
68 #include <qpushbutton.h>
70 #include <qradiobutton.h>
71 #include <qbuttongroup.h>
72 #include <qapplication.h>
73 #include <qstringlist.h>
74 #include <qcheckbox.h>
75 #include <qmessagebox.h>
77 #include <vtkProperty.h>
80 #include <SALOMEconfig.h>
81 #include CORBA_SERVER_HEADER(SMESH_Mesh)
82 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
88 * \brief Dialog to publish a sub-shape of the mesh main shape
89 * by selecting mesh elements
91 SMESHGUI_MakeNodeAtPointDlg::SMESHGUI_MakeNodeAtPointDlg()
92 : SMESHGUI_Dialog( 0, false, true )
94 setCaption(tr("CAPTION"));
96 QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame(), MARGIN, SPACING);
98 QFrame* aMainFrame = createMainFrame (mainFrame());
100 aDlgLay->addWidget(aMainFrame);
102 aDlgLay->setStretchFactor(aMainFrame, 1);
105 //=======================================================================
106 // function : createMainFrame()
107 // purpose : Create frame containing dialog's input fields
108 //=======================================================================
109 QFrame* SMESHGUI_MakeNodeAtPointDlg::createMainFrame (QWidget* theParent)
111 QFrame* aFrame = new QFrame(theParent);
113 SUIT_ResourceMgr* rm = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
114 QPixmap iconMoveNode (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_NODE")));
115 QPixmap iconSelect (rm->loadPixmap("SMESH", tr("ICON_SELECT")));
119 QButtonGroup* aPixGrp = new QButtonGroup(1, Qt::Vertical, tr("MESH_PASS_THROUGH_POINT"), aFrame);
120 aPixGrp->setExclusive(TRUE);
121 QRadioButton* aRBut = new QRadioButton(aPixGrp);
122 aRBut->setPixmap(iconMoveNode);
123 aRBut->setChecked(TRUE);
127 QGroupBox* aCoordGrp = new QGroupBox(1, Qt::Vertical, tr("SMESH_COORDINATES"), aFrame);
128 myCoordBtn = new QPushButton(aCoordGrp);
129 myCoordBtn->setPixmap(iconSelect);
130 myCoordBtn->setToggleButton(TRUE);
132 QLabel* aXLabel = new QLabel(tr("SMESH_X"), aCoordGrp);
133 aXLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
134 myX = new SMESHGUI_SpinBox(aCoordGrp);
136 QLabel* aYLabel = new QLabel(tr("SMESH_Y"), aCoordGrp);
137 aYLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs );
138 myY = new SMESHGUI_SpinBox(aCoordGrp);
140 QLabel* aZLabel = new QLabel(tr("SMESH_Z"), aCoordGrp);
141 aZLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs );
142 myZ = new SMESHGUI_SpinBox(aCoordGrp);
144 myX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 25.0, 3);
145 myY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 25.0, 3);
146 myZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 25.0, 3);
150 QButtonGroup* aMethodGrp = new QButtonGroup(1, Qt::Vertical, tr("METHOD"), aFrame);
151 aMethodGrp->setExclusive(TRUE);
152 myMoveRBtn = new QRadioButton(tr("MOVE_EXISTING_METHOD"), aMethodGrp);
153 myCreateRBtn = new QRadioButton(tr("CREATE_NEW_METHOD"), aMethodGrp);
157 myNodeToMoveGrp = new QGroupBox(tr("NODE_2MOVE"), aFrame, "anIdGrp");
159 QLabel* idLabel = new QLabel(tr("NODE_2MOVE_ID"), myNodeToMoveGrp, "idLabel");
160 myIdBtn = new QPushButton(myNodeToMoveGrp);
161 myIdBtn->setPixmap(iconSelect);
162 myIdBtn->setToggleButton(TRUE);
163 myId = new QLineEdit(myNodeToMoveGrp,"myId");
164 myId->setValidator(new SMESHGUI_IdValidator(this, "validator", 1));
165 myAutoSearchChkBox = new QCheckBox( tr("AUTO_SEARCH"), myNodeToMoveGrp, "myAutoSearchChkBox");
166 myPreviewChkBox = new QCheckBox( tr("PREVIEW"), myNodeToMoveGrp, "myPreviewChkBox");
168 myNodeToMoveGrp->setColumnLayout(0, Qt::Vertical);
169 myNodeToMoveGrp->layout()->setSpacing(0);
170 myNodeToMoveGrp->layout()->setMargin(0);
171 QGridLayout* myNodeToMoveGrpLayout = new QGridLayout(myNodeToMoveGrp->layout());
172 myNodeToMoveGrpLayout->setAlignment(Qt::AlignTop);
173 myNodeToMoveGrpLayout->setSpacing(SPACING);
174 myNodeToMoveGrpLayout->setMargin(MARGIN);
175 myNodeToMoveGrpLayout->addWidget( idLabel, 0, 0 );
176 myNodeToMoveGrpLayout->addWidget( myIdBtn, 0, 1 );
177 myNodeToMoveGrpLayout->addWidget( myId, 0, 2 );
178 myNodeToMoveGrpLayout->addMultiCellWidget( myAutoSearchChkBox, 1, 1, 0, 2 );
179 myNodeToMoveGrpLayout->addMultiCellWidget( myPreviewChkBox, 2, 2, 0, 2 );
181 QVBoxLayout* aLay = new QVBoxLayout(aFrame);
182 aLay->addWidget(aPixGrp);
183 aLay->addWidget(aCoordGrp);
184 aLay->addWidget(aMethodGrp);
185 aLay->addWidget(myNodeToMoveGrp);
187 connect(myCoordBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
188 connect(myMoveRBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
189 connect(myCreateRBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
190 connect(myIdBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
191 connect(myAutoSearchChkBox, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
193 myMoveRBtn->setChecked(TRUE);
194 myIdBtn->setOn(TRUE);
195 myAutoSearchChkBox->setChecked(TRUE);
200 //================================================================================
202 * \brief SLOT called when any button is toggled
203 * \param bool - on or off
205 //================================================================================
207 void SMESHGUI_MakeNodeAtPointDlg::ButtonToggled (bool on)
209 const QObject* aSender = sender();
211 if ( aSender == myCoordBtn ) // button to set coord by node selection
213 if ( myIdBtn->isEnabled() )
214 myIdBtn->setOn( !on );
216 else if ( aSender == myIdBtn ) // button to select a node to move
218 myCoordBtn->setOn( !on );
220 else if ( aSender == myMoveRBtn ) // move node method
222 myNodeToMoveGrp->setEnabled( TRUE );
224 else if ( aSender == myCreateRBtn ) // create node method
226 myNodeToMoveGrp->setEnabled( FALSE );
227 myCoordBtn->setOn( TRUE );
230 if ( aSender == myAutoSearchChkBox ) // automatic node search
234 myId->setReadOnly ( TRUE );
235 myIdBtn->setOn( FALSE );
236 myIdBtn->setEnabled( FALSE );
237 myCoordBtn->setOn( TRUE );
240 myId->setReadOnly ( FALSE );
241 myIdBtn->setEnabled( TRUE );
246 //================================================================================
250 //================================================================================
252 SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp()
255 myDlg = new SMESHGUI_MakeNodeAtPointDlg;
257 // connect signals and slots
258 connect(myDlg->myX, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
259 connect(myDlg->myY, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
260 connect(myDlg->myZ, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
261 connect(myDlg->myId,SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview()));
262 connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
263 connect(myDlg->myAutoSearchChkBox,SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
264 connect(myDlg->myMoveRBtn, SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
265 connect(myDlg->myCreateRBtn, SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
268 //=======================================================================
269 // function : startOperation()
270 // purpose : Init dialog fields, connect signals and slots, show dialog
271 //=======================================================================
272 void SMESHGUI_MakeNodeAtPointOp::startOperation()
277 // init simulation with a current View
278 if ( mySimulation ) delete mySimulation;
279 mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( getSMESHGUI() ));
280 vtkProperty* aProp = vtkProperty::New();
281 aProp->SetRepresentationToWireframe();
282 aProp->SetColor(250, 0, 250);
283 aProp->SetPointSize(5);
284 aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1);
285 mySimulation->GetActor()->SetProperty(aProp);
288 SMESHGUI_SelectionOp::startOperation();
290 activateSelection(); // set filters
292 myDlg->myX->SetValue(0);
293 myDlg->myY->SetValue(0);
294 myDlg->myZ->SetValue(0);
295 myDlg->myId->setText("");
298 onSelectionDone(); // init myMeshActor
301 // myMeshOldDisplayMode = myMeshActor->GetRepresentation();
302 // myMeshActor->SetRepresentation( VTK_WIREFRAME );
303 myMeshActor->SetPointRepresentation(true);
304 SMESH::RepaintCurrentView();
309 //================================================================================
311 * \brief Stops operation
313 //================================================================================
315 void SMESHGUI_MakeNodeAtPointOp::stopOperation()
318 mySimulation->SetVisibility(false);
320 // myMeshActor->SetRepresentation( myMeshOldDisplayMode );
321 myMeshActor->SetPointRepresentation(false);
322 SMESH::RepaintCurrentView();
324 SMESHGUI_SelectionOp::stopOperation();
327 //================================================================================
329 * \brief perform it's intention action: move or create a node
331 //================================================================================
333 bool SMESHGUI_MakeNodeAtPointOp::onApply()
335 if ( !isValid() ) return false; // node id is invalid
337 if ( !myMeshActor ) return true;
340 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
341 if (aMesh->_is_nil()) {
342 QMessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"),
343 tr("SMESHG_NO_MESH"), QMessageBox::Ok);
346 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
347 if (aMeshEditor->_is_nil())
351 if ( myDlg->myCreateRBtn->isOn() )
353 aResult = aMeshEditor->AddNode(myDlg->myX->GetValue(),
354 myDlg->myY->GetValue(),
355 myDlg->myZ->GetValue());
359 int anId = myDlg->myId->text().toInt();
360 aResult = aMeshEditor->MoveClosestNodeToPoint(myDlg->myX->GetValue(),
361 myDlg->myY->GetValue(),
362 myDlg->myZ->GetValue(),
367 myDlg->myId->setText("");
370 aList.Append(myMeshActor->getIO());
371 selectionMgr()->setSelectedObjects(aList,false);
375 catch (const SALOME::SALOME_Exception& S_ex) {
376 SalomeApp_Tools::QtCatchCorbaException(S_ex);
384 //================================================================================
386 * \brief Check data validity
388 //================================================================================
390 bool SMESHGUI_MakeNodeAtPointOp::isValid()
395 myDlg->myMoveRBtn->isOn() &&
396 !myDlg->myAutoSearchChkBox->isChecked() )
399 int id = myDlg->myId->text().toInt();
401 if (SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh())
402 ok = aMesh->FindNode( id );
407 //================================================================================
409 * \brief SLOT called when selection changed
411 //================================================================================
413 void SMESHGUI_MakeNodeAtPointOp::onSelectionDone()
415 if ( !myDlg->isShown() || !myDlg->isEnabled() )
419 selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type());
420 if (aList.Extent() != 1)
422 Handle(SALOME_InteractiveObject) anIO = aList.First();
423 SMESH_Actor* aMeshActor = SMESH::FindActorByEntry(anIO->getEntry());
427 myMeshActor = aMeshActor;
429 int nbElems = SMESH::GetNameOfSelectedElements(selector(),anIO, aString);
431 if (SMDS_Mesh* aMesh = aMeshActor->GetObject()->GetMesh()) {
432 if (const SMDS_MeshNode* aNode = aMesh->FindNode(aString.toInt())) {
434 if ( myDlg->myCoordBtn->isOn() ) { // set coord
435 myDlg->myX->SetValue(aNode->X());
436 myDlg->myY->SetValue(aNode->Y());
437 myDlg->myZ->SetValue(aNode->Z());
441 else if ( myDlg->myIdBtn->isOn() &&
442 myDlg->myIdBtn->isEnabled() ) { // set node to move
443 myDlg->myId->setText(aString);
454 //================================================================================
456 * \brief update preview
458 //================================================================================
460 void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
466 SMESH::MeshPreviewStruct_var aMeshPreviewStruct;
468 bool moveShown = false;
469 if ( myDlg->myMoveRBtn->isOn() && // Move method
472 const bool autoSearch = myDlg->myAutoSearchChkBox->isChecked();
473 const bool preview = myDlg->myPreviewChkBox->isChecked();
475 myDlg->myId->setText("");
476 if ( preview && ( autoSearch || isValid() ))
479 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
480 if (!aMesh->_is_nil()) {
481 SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer();
482 if (!aPreviewer->_is_nil())
484 SUIT_OverrideCursor aWaitCursor;
486 // find id and/or just compute preview
487 int anId = aPreviewer->MoveClosestNodeToPoint(myDlg->myX->GetValue(),
488 myDlg->myY->GetValue(),
489 myDlg->myZ->GetValue(),
490 myDlg->myId->text().toInt());
491 if ( autoSearch ) { // set found id
494 idTxt = idTxt.arg( anId );
497 myDlg->myId->setText( idTxt );
499 if ( preview ) { // fill preview data
500 aMeshPreviewStruct = aPreviewer->GetPreviewData();
501 moveShown = ( anId > 0 );
512 aMeshPreviewStruct = new SMESH::MeshPreviewStruct();
514 aMeshPreviewStruct->nodesXYZ.length(1);
515 aMeshPreviewStruct->nodesXYZ[0].x = myDlg->myX->GetValue();
516 aMeshPreviewStruct->nodesXYZ[0].y = myDlg->myY->GetValue();
517 aMeshPreviewStruct->nodesXYZ[0].z = myDlg->myZ->GetValue();
519 aMeshPreviewStruct->elementTypes.length(1);
520 aMeshPreviewStruct->elementTypes[0].SMDS_ElementType = SMESH::NODE;
521 aMeshPreviewStruct->elementTypes[0].isPoly = false;
522 aMeshPreviewStruct->elementTypes[0].nbNodesInElement = 1;
524 aMeshPreviewStruct->elementConnectivities.length(1);
525 aMeshPreviewStruct->elementConnectivities[0] = 0;
529 if ( aMeshPreviewStruct.operator->() )
531 mySimulation->SetData(aMeshPreviewStruct._retn());
535 mySimulation->SetVisibility(false);
541 //================================================================================
543 * \brief Activate Node selection
545 //================================================================================
547 void SMESHGUI_MakeNodeAtPointOp::activateSelection()
549 selectionMgr()->clearFilters();
550 SMESH::SetPointRepresentation(false);
551 setSelectionMode( NodeSelection );
554 //================================================================================
558 //================================================================================
560 SMESHGUI_MakeNodeAtPointOp::~SMESHGUI_MakeNodeAtPointOp()
567 //================================================================================
569 * \brief Gets dialog of this operation
570 * \retval LightApp_Dialog* - pointer to dialog of this operation
572 //================================================================================
574 LightApp_Dialog* SMESHGUI_MakeNodeAtPointOp::dlg() const