1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 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
23 // GEOM GEOMGUI : GUI for Geometry component
24 // File : MeasureGUI_DistanceDlg.cxx
25 // Author : Nicolas REJNERI, Open CASCADE S.A.S.
27 #include "MeasureGUI_DistanceDlg.h"
28 #include "MeasureGUI_Widgets.h"
32 #include <GeometryGUI.h>
34 #include <SUIT_Session.h>
35 #include <SUIT_Desktop.h>
36 #include <SUIT_ResourceMgr.h>
37 #include <SUIT_ViewWindow.h>
38 #include <SUIT_ViewManager.h>
39 #include <SUIT_OverrideCursor.h>
40 #include <SUIT_MessageBox.h>
42 #include <SOCC_ViewModel.h>
43 #include <SalomeApp_Tools.h>
44 #include <SalomeApp_Application.h>
45 #include <LightApp_SelectionMgr.h>
48 #include <Geom_Plane.hxx>
49 #include <AIS_LengthDimension.hxx>
50 #include <AIS_Drawer.hxx>
51 #include <Prs3d_LengthAspect.hxx>
52 #include <Prs3d_LineAspect.hxx>
53 #include <BRepBuilderAPI_MakeEdge.hxx>
54 #include <BRepBuilderAPI_MakeVertex.hxx>
55 #include <gce_MakePln.hxx>
56 #include <Precision.hxx>
58 //=================================================================================
59 // class : MeasureGUI_DistanceDlg()
60 // purpose : Constructs a MeasureGUI_DistanceDlg which is a child of 'parent', with the
61 // name 'name' and widget flags set to 'f'.
62 // The dialog will by default be modeless, unless you set 'modal' to
63 // true to construct a modal dialog.
64 //=================================================================================
65 MeasureGUI_DistanceDlg::MeasureGUI_DistanceDlg (GeometryGUI* GUI, QWidget* parent)
66 : GEOMBase_Skeleton(GUI, parent)
68 SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
69 QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_MINDIST")));
70 QPixmap image1 (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT")));
72 setWindowTitle(tr("GEOM_MINDIST_TITLE"));
74 /***************************************************************/
75 mainFrame()->GroupConstructors->setTitle(tr("GEOM_DISTANCE"));
76 mainFrame()->RadioButton1->setIcon(image0);
77 mainFrame()->RadioButton2->setAttribute(Qt::WA_DeleteOnClose);
78 mainFrame()->RadioButton2->close();
79 mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
80 mainFrame()->RadioButton3->close();
82 mainFrame()->GroupBoxName->hide();
84 myGrp = new MeasureGUI_DistanceGroup (centralWidget());
85 myGrp->GroupBox1->setTitle(tr("GEOM_MINDIST_OBJ"));
88 myGrp->TextLabel1->setText(tr("GEOM_OBJECT_I").arg("1"));
89 myGrp->TextLabel2->setText(tr("GEOM_OBJECT_I").arg("2"));
90 myGrp->PushButton1->setIcon(image1);
91 myGrp->PushButton2->setIcon(image1);
92 myGrp->LineEdit1->setReadOnly(true);
93 myGrp->LineEdit2->setReadOnly(true);
96 myGrp->TextLabel7->setText(tr("GEOM_SOLUTION"));
98 // Distance, dx, dy and dz
99 myGrp->TextLabel3->setText(tr("GEOM_LENGTH"));
100 myGrp->TextLabel4->setText(tr("GEOM_DX"));
101 myGrp->TextLabel5->setText(tr("GEOM_DY"));
102 myGrp->TextLabel6->setText(tr("GEOM_DZ"));
103 myGrp->LineEdit3->setReadOnly(true);
104 myGrp->LineEdit4->setReadOnly(true);
105 myGrp->LineEdit5->setReadOnly(true);
106 myGrp->LineEdit6->setReadOnly(true);
107 /***************************************************************/
109 myHelpFileName = "min_distance_page.html";
115 //=================================================================================
116 // function : ~MeasureGUI_DistanceDlg()
117 // purpose : Destroys the object and frees any allocated resources
118 //=================================================================================
119 MeasureGUI_DistanceDlg::~MeasureGUI_DistanceDlg()
123 //=================================================================================
126 //=================================================================================
127 void MeasureGUI_DistanceDlg::Init()
129 myEditCurrentArgument = myGrp->LineEdit1;
130 myDbls = new GEOM::ListOfDouble();
132 // signals and slots connections
133 connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk()));
134 connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
136 connect(myGrp->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
137 connect(myGrp->PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
139 connect(myGrp->ComboBox1, SIGNAL(currentIndexChanged(int)), this, SLOT(SolutionSelected(int)));
141 connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
142 this, SLOT(SelectionIntoArgument()));
145 SelectionIntoArgument();
148 //=================================================================================
149 // function : ClickOnOk()
151 //=================================================================================
152 void MeasureGUI_DistanceDlg::ClickOnOk()
158 //=================================================================================
159 // function : ClickOnApply()
161 //=================================================================================
162 bool MeasureGUI_DistanceDlg::ClickOnApply()
171 //=================================================================================
172 // function : ActivateThisDialog()
174 //=================================================================================
175 void MeasureGUI_DistanceDlg::ActivateThisDialog()
177 GEOMBase_Skeleton::ActivateThisDialog();
179 connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
180 this, SLOT(SelectionIntoArgument()));
186 //=================================================================================
187 // function : enterEvent()
189 //=================================================================================
190 void MeasureGUI_DistanceDlg::enterEvent(QEvent*)
192 if (!mainFrame()->GroupConstructors->isEnabled())
193 ActivateThisDialog();
196 //=================================================================================
197 // function : SolutionSelected()
198 // purpose : Called when ComboBox selection has changed
199 //=================================================================================
200 void MeasureGUI_DistanceDlg::SolutionSelected (int i)
202 if (i < 0 || myDbls->length() < (i+1)*6) {
203 myGrp->LineEdit3->setText("");
204 myGrp->LineEdit4->setText("");
205 myGrp->LineEdit5->setText("");
206 myGrp->LineEdit6->setText("");
211 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
212 int aPrecision = resMgr->integerValue( "Geometry", "length_precision", 6 );
214 gp_Pnt p1 (myDbls[i*6 + 0], myDbls[i*6 + 1], myDbls[i*6 + 2]);
215 gp_Pnt p2 (myDbls[i*6 + 3], myDbls[i*6 + 4], myDbls[i*6 + 5]);
217 double aDist = p1.Distance(p2);
218 myGrp->LineEdit3->setText(DlgRef::PrintDoubleValue(aDist, aPrecision));
220 gp_XYZ aVec = p2.XYZ() - p1.XYZ();
221 myGrp->LineEdit4->setText(DlgRef::PrintDoubleValue(aVec.X(), aPrecision));
222 myGrp->LineEdit5->setText(DlgRef::PrintDoubleValue(aVec.Y(), aPrecision));
223 myGrp->LineEdit6->setText(DlgRef::PrintDoubleValue(aVec.Z(), aPrecision));
228 //=================================================================================
229 // function : SelectionIntoArgument()
230 // purpose : Called when selection has changed
231 //=================================================================================
232 void MeasureGUI_DistanceDlg::SelectionIntoArgument()
234 LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
235 SALOME_ListIO aSelList;
236 aSelMgr->selectedObjects(aSelList);
238 GEOM::GEOM_Object_var aSelectedObject = GEOM::GEOM_Object::_nil();
240 if (aSelList.Extent() > 0) {
241 aSelectedObject = GEOMBase::ConvertIOinGEOMObject(aSelList.First());
245 disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
246 myGeomGUI->getApp()->selectionMgr()->clearSelected();
247 connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
248 this, SLOT(SelectionIntoArgument()));
250 if (myEditCurrentArgument == myGrp->LineEdit1) {
251 myObj1 = aSelectedObject;
252 if (!myObj1->_is_nil() && myObj2->_is_nil())
253 myGrp->PushButton2->click();
256 myObj2 = aSelectedObject;
257 if (!myObj2->_is_nil() && myObj1->_is_nil())
258 myGrp->PushButton1->click();
264 //=================================================================================
265 // function : SetEditCurrentArgument()
267 //=================================================================================
268 void MeasureGUI_DistanceDlg::SetEditCurrentArgument()
270 QPushButton* send = (QPushButton*)sender();
272 if (send == myGrp->PushButton1) {
273 myEditCurrentArgument = myGrp->LineEdit1;
275 myGrp->PushButton2->setDown(false);
276 myGrp->LineEdit2->setEnabled(false);
279 myEditCurrentArgument = myGrp->LineEdit2;
281 myGrp->PushButton1->setDown(false);
282 myGrp->LineEdit1->setEnabled(false);
286 myEditCurrentArgument->setEnabled(true);
287 myEditCurrentArgument->setFocus();
288 // after setFocus(), because it will be setDown(false) when loses focus
291 // seems we need it only to avoid preview disappearing, caused by selection mode change
295 //=================================================================================
296 // function : processObject()
297 // purpose : Fill dialogs fields in accordance with myObj1 and myObj2
298 //=================================================================================
299 void MeasureGUI_DistanceDlg::processObject()
301 myGrp->LineEdit1->setText(!myObj1->_is_nil() ? GEOMBase::GetName(myObj1) : "");
302 myGrp->LineEdit2->setText(!myObj2->_is_nil() ? GEOMBase::GetName(myObj2) : "");
304 myGrp->ComboBox1->clear();
311 if (!isValid(msg)) return;
313 GEOM::GEOM_IMeasureOperations_var anOper = GEOM::GEOM_IMeasureOperations::_narrow(getOperation());
315 nbSols = anOper->ClosestPoints(myObj1, myObj2, myDbls);
317 catch (const SALOME::SALOME_Exception& e) {
318 SalomeApp_Tools::QtCatchCorbaException(e);
322 if (!anOper->IsDone())
323 myGrp->ComboBox1->addItem(tr(anOper->GetErrorCode()));
324 else if (nbSols <= 0)
325 myGrp->ComboBox1->addItem(tr("GEOM_MINDIST_NO_SOL"));
327 for (int i = 0; i < nbSols; i++) {
328 myGrp->ComboBox1->addItem(tr("GEOM_SOLUTION_I").arg(i + 1));
330 myGrp->ComboBox1->setCurrentIndex(0);
334 //=================================================================================
335 // function : buildPrs()
337 //=================================================================================
338 SALOME_Prs* MeasureGUI_DistanceDlg::buildPrs()
340 SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
342 int currSol = myGrp->ComboBox1->currentIndex();
344 if (myObj1->_is_nil() || myObj2->_is_nil() ||
345 currSol == -1 || (currSol+1)*6 > myDbls->length() ||
346 vw->getViewManager()->getType() != OCCViewer_Viewer::Type())
349 gp_Pnt aPnt1 (myDbls[currSol*6 + 0], myDbls[currSol*6 + 1], myDbls[currSol*6 + 2]);
350 gp_Pnt aPnt2 (myDbls[currSol*6 + 3], myDbls[currSol*6 + 4], myDbls[currSol*6 + 5]);
352 double aDist = aPnt1.Distance(aPnt2);
356 if (aDist <= 1.e-9) {
357 BRepBuilderAPI_MakeVertex aMaker (aPnt1);
358 return getDisplayer()->BuildPrs(aMaker.Vertex());
361 BRepBuilderAPI_MakeEdge MakeEdge (aPnt1, aPnt2);
362 TopoDS_Vertex aVert1 = BRepBuilderAPI_MakeVertex(aPnt1);
363 TopoDS_Vertex aVert2 = BRepBuilderAPI_MakeVertex(aPnt2);
366 aLabel.sprintf("%.1f", aDist);
368 gp_Pnt aPnt3 ((aPnt1.X() + aPnt2.X()) / 2,
369 (aPnt1.Y() + aPnt2.Y()) / 2,
370 (aPnt1.Z() + aPnt2.Z()) / 2);
372 gp_Vec va (aPnt3, aPnt1);
373 gp_Vec vb (aPnt3, aPnt2);
375 if (va.IsParallel(vb, Precision::Angular())) {
376 aPnt3.SetY((aPnt1.Y() + aPnt2.Y()) / 2 + 100);
377 aPnt3.SetZ((aPnt1.Z() + aPnt2.Z()) / 2);
380 gce_MakePln gce_MP (aPnt1, aPnt2, aPnt3);
381 Handle(Geom_Plane) P = new Geom_Plane (gce_MP.Value());
383 Handle(AIS_LengthDimension) anIO = new AIS_LengthDimension
384 (aVert1, aVert2, P, aDist,
385 TCollection_ExtendedString((Standard_CString)aLabel.toLatin1().constData()));
386 anIO->SetArrowSize(aDist/20);
388 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
389 int w = resMgr->integerValue("Geometry", "measures_line_width", 1);
390 Handle(Prs3d_LengthAspect) asp = new Prs3d_LengthAspect();
391 asp->LineAspect()->SetWidth(w);
392 anIO->Attributes()->SetLengthAspect(asp);
394 SOCC_Prs* aPrs = dynamic_cast<SOCC_Prs*>(((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0));
397 aPrs->AddObject(anIO);
402 catch (Standard_Failure) {
407 //=================================================================================
408 // function : createOperation
410 //=================================================================================
411 GEOM::GEOM_IOperations_ptr MeasureGUI_DistanceDlg::createOperation()
413 return getGeomEngine()->GetIMeasureOperations(getStudyId());
416 //=================================================================================
417 // function : isValid()
419 //=================================================================================
420 bool MeasureGUI_DistanceDlg::isValid (QString& msg)
422 return !myObj1->_is_nil() && !myObj2->_is_nil();
425 //=================================================================================
426 // function : execute
428 //=================================================================================
429 bool MeasureGUI_DistanceDlg::execute (ObjectList& objects)
431 GEOM::GEOM_IMeasureOperations_var anOper = GEOM::GEOM_IMeasureOperations::_narrow(getOperation());
432 GEOM::GEOM_IBasicOperations_var aBasicOper = getGeomEngine()->GetIBasicOperations(getStudyId());
434 GEOM::ListOfDouble_var aDbls;
435 int nbSols = anOper->ClosestPoints(myObj1, myObj2, aDbls);
437 if (anOper->IsDone()) {
438 bool doPublishAll = true;
440 QMessageBox::StandardButton anAnswer =
441 SUIT_MessageBox::question(this, tr("GEOM_MINDIST_PUBLISH_TITLE"),
442 tr("GEOM_MINDIST_PUBLISH_TEXT"),
443 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
445 if (anAnswer == QMessageBox::No)
446 doPublishAll = false;
447 else if (anAnswer != QMessageBox::Yes)
451 for (int i = 0; i < nbSols; i++) {
452 GEOM::GEOM_Object_var anObj1 =
453 aBasicOper->MakePointXYZ(aDbls[i*6 + 0], aDbls[i*6 + 1], aDbls[i*6 + 2]);
454 GEOM::GEOM_Object_var anObj2 =
455 aBasicOper->MakePointXYZ(aDbls[i*6 + 3], aDbls[i*6 + 4], aDbls[i*6 + 5]);
457 if (!anObj1->_is_nil() && !anObj2->_is_nil()) {
458 objects.push_back(anObj1._retn());
459 objects.push_back(anObj2._retn());
464 int i = myGrp->ComboBox1->currentIndex();
465 GEOM::GEOM_Object_var anObj1 =
466 aBasicOper->MakePointXYZ(aDbls[i*6 + 0], aDbls[i*6 + 1], aDbls[i*6 + 2]);
467 GEOM::GEOM_Object_var anObj2 =
468 aBasicOper->MakePointXYZ(aDbls[i*6 + 3], aDbls[i*6 + 4], aDbls[i*6 + 5]);
470 if (!anObj1->_is_nil() && !anObj2->_is_nil()) {
471 objects.push_back(anObj1._retn());
472 objects.push_back(anObj2._retn());
480 //=================================================================================
481 // function : redisplayPreview()
483 //=================================================================================
484 void MeasureGUI_DistanceDlg::redisplayPreview()
487 if (!isValid(aMess)) {
495 SUIT_OverrideCursor();
497 getDisplayer()->SetColor(Quantity_NOC_VIOLET);
498 getDisplayer()->SetToActivate(false);
500 if (SALOME_Prs* aPrs = buildPrs())
501 displayPreview(aPrs);
503 catch (const SALOME::SALOME_Exception& e) {
504 SalomeApp_Tools::QtCatchCorbaException(e);
508 //================================================================
509 // Function : getNewObjectName
510 // Purpose : Redefine this method to return proper name for a new object
511 //================================================================
512 QString MeasureGUI_DistanceDlg::getNewObjectName (int currObj) const
514 QString aName = tr("GEOM_MINDIST_NAME") + QString("_%1_").arg((currObj+1)/2);
515 aName += GEOMBase::GetName(currObj%2 ? myObj1 : myObj2);
520 //=================================================================================
521 // function : MeasureGUI_DistanceGroup
523 //=================================================================================
524 MeasureGUI_DistanceGroup::MeasureGUI_DistanceGroup (QWidget *parent)
526 gridLayout = new QGridLayout (parent);
527 gridLayout->setSpacing(6);
528 gridLayout->setContentsMargins(11, 11, 11, 11);
529 gridLayout->setHorizontalSpacing(0);
530 gridLayout->setVerticalSpacing(0);
531 gridLayout->setContentsMargins(0, 0, 0, 0);
533 GroupBox1 = new QGroupBox (parent);
535 gridLayout1 = new QGridLayout (GroupBox1);
536 gridLayout1->setSpacing(6);
537 gridLayout1->setContentsMargins(11, 11, 11, 11);
538 gridLayout1->setHorizontalSpacing(6);
539 gridLayout1->setVerticalSpacing(6);
540 gridLayout1->setContentsMargins(9, 9, 9, 9);
543 TextLabel1 = new QLabel(GroupBox1);
544 TextLabel2 = new QLabel(GroupBox1);
546 PushButton1 = new QPushButton (GroupBox1);
547 PushButton2 = new QPushButton (GroupBox1);
549 LineEdit1 = new QLineEdit(GroupBox1);
550 LineEdit2 = new QLineEdit(GroupBox1);
552 gridLayout1->addWidget(TextLabel1, 0, 0, 1, 1);
553 gridLayout1->addWidget(TextLabel2, 1, 0, 1, 1);
554 gridLayout1->addWidget(PushButton1, 0, 1, 1, 1);
555 gridLayout1->addWidget(PushButton2, 1, 1, 1, 1);
556 gridLayout1->addWidget(LineEdit1, 0, 2, 1, 1);
557 gridLayout1->addWidget(LineEdit2, 1, 2, 1, 1);
560 TextLabel7 = new QLabel (GroupBox1);
562 ComboBox1 = new QComboBox (GroupBox1);
564 gridLayout1->addWidget(TextLabel7, 2, 0, 1, 1);
565 gridLayout1->addWidget(ComboBox1, 2, 1, 1, 2);
568 TextLabel3 = new QLabel (GroupBox1);
569 TextLabel4 = new QLabel (GroupBox1);
570 TextLabel5 = new QLabel (GroupBox1);
571 TextLabel6 = new QLabel (GroupBox1);
573 LineEdit3 = new QLineEdit(GroupBox1);
574 LineEdit4 = new QLineEdit(GroupBox1);
575 LineEdit5 = new QLineEdit(GroupBox1);
576 LineEdit6 = new QLineEdit(GroupBox1);
578 gridLayout1->addWidget(TextLabel3, 3, 0, 1, 1);
579 gridLayout1->addWidget(TextLabel4, 4, 0, 1, 1);
580 gridLayout1->addWidget(TextLabel5, 5, 0, 1, 1);
581 gridLayout1->addWidget(TextLabel6, 6, 0, 1, 1);
583 gridLayout1->addWidget(LineEdit3, 3, 1, 1, 2);
584 gridLayout1->addWidget(LineEdit4, 4, 1, 1, 2);
585 gridLayout1->addWidget(LineEdit5, 5, 1, 1, 2);
586 gridLayout1->addWidget(LineEdit6, 6, 1, 1, 2);
588 gridLayout->addWidget(GroupBox1, 0, 0, 1, 1);
591 //=================================================================================
592 // function : ~MeasureGUI_DistanceGroup()
593 // purpose : Destroys the object and frees any allocated resources
594 //=================================================================================
595 MeasureGUI_DistanceGroup::~MeasureGUI_DistanceGroup()
597 // no need to delete child widgets, Qt does it all for us