Salome HOME
ac96361e0053a42bd614a1470bfb405ad542a577
[modules/geom.git] / src / MeasureGUI / MeasureGUI_CheckSelfIntersectionsDlg.cxx
1 // Copyright (C) 2007-2023  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 // GEOM GEOMGUI : GUI for Geometry component
24 // File   : MeasureGUI_CheckSelfIntersectionsDlg.cxx
25
26 #include "MeasureGUI_CheckSelfIntersectionsDlg.h"
27 #include "MeasureGUI.h"
28
29 #include <SUIT_MessageBox.h>
30 #include <SUIT_OverrideCursor.h>
31 #include <SUIT_Session.h>
32 #include <SUIT_ResourceMgr.h>
33 #include <LightApp_SelectionMgr.h>
34 #include <SalomeApp_Tools.h>
35 #include <SalomeApp_Application.h>
36
37 #include <TopTools_IndexedMapOfShape.hxx>
38 #include <TopExp.hxx>
39 #include <TColStd_IndexedMapOfInteger.hxx>
40 #include <TColStd_MapOfInteger.hxx>
41
42 #include <DlgRef.h>
43 #include <GeometryGUI.h>
44 #include <GEOMBase.h>
45 #include <GEOMImpl_Types.hxx>
46 #include <GEOM_GenericObjPtr.h>
47
48 #include <QListWidget>
49
50 #define TEXTEDIT_FONT_FAMILY "Courier"
51 #define TEXTEDIT_FONT_SIZE 11
52
53 //=================================================================================
54 // class    : MeasureGUI_CheckSelfIntersectionsDlg()
55 // purpose  : Constructs a MeasureGUI_CheckSelfIntersectionsDlg which is a child of 'parent', with the
56 //            name 'name' and widget flags set to 'f'.
57 //            The dialog will by default be modeless, unless you set 'modal' to
58 //            true to construct a modal dialog.
59 //=================================================================================
60 MeasureGUI_CheckSelfIntersectionsDlg::MeasureGUI_CheckSelfIntersectionsDlg (GeometryGUI* GUI, QWidget* parent)
61   : GEOMBase_Skeleton (GUI, parent, false),
62     myCurrConstrId    (-1),
63     myComputeButton1  (0),
64     myTextView1       (0),
65     mySelButton1      (0),
66     myEditObjName1    (0),
67     myLevelBox        (0),
68     myInteList1       (0),
69     myShapeList1      (0),
70     myComputeButton2  (0),
71     myTextView2       (0),
72     mySelButton2      (0),
73     myEditObjName2    (0),
74     myInteList2       (0),
75     myShapeList2      (0)
76 {
77   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
78   QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_CHECK_SELF_INTERSECTIONS")));
79   QPixmap image1 (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT")));
80   QPixmap image2 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_FAST_CHECK_INTERSECTIONS")));
81
82   setWindowTitle(tr("GEOM_CHECK_SELF_INTERSECTIONS"));
83
84   /***************************************************************/
85   mainFrame()->GroupConstructors->setTitle(tr("GEOM_CHECK_INTERSECT_TYPE"));
86   mainFrame()->RadioButton1->setIcon(image0);
87   mainFrame()->RadioButton2->setIcon(image2);;
88   mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose );
89   mainFrame()->RadioButton3->close();
90
91   /***************************************************************/
92   // SIMPLE SELF-INTERSECTION constructor
93   /***************************************************************/
94   mySimpleGrp             = new QGroupBox(tr("GEOM_CHECK_INFOS"));
95   QLabel    *anObjLbl    = new QLabel(tr("GEOM_OBJECT"));
96   QLabel    *anInteLbl   = new QLabel(tr("GEOM_CHECK_INTE_INTERSECTIONS"));
97   QLabel    *aShapeLbl   = new QLabel(tr("GEOM_CHECK_INTE_SUBSHAPES"));
98   QLabel    *aLevelLbl   = new QLabel(tr("GEOM_CHECK_INTE_CHECK_LEVEL"));
99   QLabel    *aSummaryLbl1 = new QLabel(tr("GEOM_CHECK_INTE_SUMMARY"));
100   QFont      aFont (TEXTEDIT_FONT_FAMILY, TEXTEDIT_FONT_SIZE);
101
102   aFont.setStyleHint(QFont::TypeWriter, QFont::PreferAntialias);
103   myTextView1 = new QTextBrowser;
104   myTextView1->setReadOnly(true);
105   myTextView1->setFont(aFont);
106
107   mySelButton1 = new QPushButton;
108   mySelButton1->setIcon(image1);
109   mySelButton1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
110
111   myEditObjName1 = new QLineEdit;
112   myEditObjName1->setReadOnly(true);
113
114   myLevelBox = new QComboBox;
115
116   myComputeButton1 = new QPushButton(tr("GEOM_CHECK_INTE_COMPUTE"));
117
118
119   myInteList1  = new QListWidget;
120   myInteList1->setSelectionMode(QAbstractItemView::ExtendedSelection);
121   myShapeList1 = new QListWidget;
122   myShapeList1->setSelectionMode(QAbstractItemView::ExtendedSelection);
123
124   QGridLayout *aGrpLayout1 = new QGridLayout(mySimpleGrp);
125
126   aGrpLayout1->setMargin(9);
127   aGrpLayout1->setSpacing(6);
128   aGrpLayout1->addWidget(anObjLbl,         0, 0);
129   aGrpLayout1->addWidget(mySelButton1,     0, 1);
130   aGrpLayout1->addWidget(myEditObjName1,   0, 2);
131   aGrpLayout1->addWidget(aLevelLbl,        1, 0);
132   aGrpLayout1->addWidget(myLevelBox,       1, 1, 1, 2);
133   aGrpLayout1->addWidget(myComputeButton1, 2, 0, 1, 3);
134   aGrpLayout1->addWidget(aSummaryLbl1,     3, 0);
135   aGrpLayout1->addWidget(myTextView1,      4, 0, 1, 3);
136   aGrpLayout1->addWidget(anInteLbl,        5, 0);
137   aGrpLayout1->addWidget(aShapeLbl,        5, 2);
138   aGrpLayout1->addWidget(myInteList1,      6, 0, 1, 2);
139   aGrpLayout1->addWidget(myShapeList1,     6, 2);
140
141   /***************************************************************/
142   // FAST SELF-INTERSECTION constructor
143   /***************************************************************/
144   
145   myFastGrp               = new QGroupBox(tr("GEOM_CHECK_INFOS"), centralWidget());
146   QLabel    *anObjLbl2    = new QLabel(tr("GEOM_OBJECT"), myFastGrp);
147   QLabel    *aDeflectLbl  = new QLabel(tr("GEOM_CHECK_INT_DEFLECT"), myFastGrp);
148   QLabel    *aSummaryLbl2 = new QLabel(tr("GEOM_CHECK_INTE_SUMMARY"));
149   QLabel    *anInteLbl2   = new QLabel(tr("GEOM_CHECK_INTE_INTERSECTIONS"), myFastGrp);
150   QLabel    *aShapeLbl2   = new QLabel(tr("GEOM_CHECK_INTE_SUBSHAPES"), myFastGrp);
151
152   mySelButton2 = new QPushButton(myFastGrp);
153   mySelButton2->setIcon(image1);
154   mySelButton2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
155
156   myEditObjName2 = new QLineEdit(myFastGrp);
157   myEditObjName2->setReadOnly(true);
158
159   myDeflection = new SalomeApp_DoubleSpinBox(myFastGrp);
160   myDetGaps = new QCheckBox(tr( "GEOM_CHECK_INT_DETECT_GAPS" ));
161   myTolerance = new SalomeApp_DoubleSpinBox(myFastGrp);
162
163   myComputeButton2 = new QPushButton(tr("GEOM_CHECK_INTE_COMPUTE"));
164
165   myTextView2 = new QTextBrowser;
166   myTextView2->setReadOnly(true);
167   myTextView2->setFont(aFont);
168
169   myInteList2  = new QListWidget(myFastGrp);
170   myInteList2->setSelectionMode(QAbstractItemView::ExtendedSelection);
171   myShapeList2 = new QListWidget(myFastGrp);
172   myShapeList2->setSelectionMode(QAbstractItemView::ExtendedSelection);
173
174   QGridLayout *aGrpLayout2 = new QGridLayout(myFastGrp);
175   aGrpLayout2->setMargin(9);
176   aGrpLayout2->setSpacing(6);
177   aGrpLayout2->addWidget(anObjLbl2,        0, 0);
178   aGrpLayout2->addWidget(mySelButton2,     0, 1);
179   aGrpLayout2->addWidget(myEditObjName2,   0, 2);
180   aGrpLayout2->addWidget(aDeflectLbl,      1, 0);
181   aGrpLayout2->addWidget(myDeflection,     1, 1, 1, 2);
182   aGrpLayout2->addWidget(myDetGaps,        2, 0);
183   aGrpLayout2->addWidget(myTolerance,      2, 1, 1, 2);
184   aGrpLayout2->addWidget(myComputeButton2, 3, 0, 1, 3);
185   aGrpLayout2->addWidget(aSummaryLbl2,     4, 0);
186   aGrpLayout2->addWidget(myTextView2,      5, 0, 1, 3);
187   aGrpLayout2->addWidget(anInteLbl2,       6, 0);
188   aGrpLayout2->addWidget(aShapeLbl2,       6, 1, 1, 2);
189   aGrpLayout2->addWidget(myInteList2,      7, 0);
190   aGrpLayout2->addWidget(myShapeList2,     7, 1, 1, 2);
191   
192   /***************************************************************/
193
194   QVBoxLayout* layout2 = new QVBoxLayout (centralWidget());
195   layout2->setMargin(0); layout2->setSpacing(6);
196   layout2->addWidget(mySimpleGrp);
197   layout2->addWidget(myFastGrp);
198
199  /***************************************************************/
200
201   myHelpFileName = "check_self_intersections_page.html";
202
203   /* Initialisation */
204   Init();
205 }
206
207 //=================================================================================
208 // function : ~MeasureGUI_CheckSelfIntersectionsDlg()
209 // purpose  : Destroys the object and frees any allocated resources
210 //=================================================================================
211 MeasureGUI_CheckSelfIntersectionsDlg::~MeasureGUI_CheckSelfIntersectionsDlg()
212 {
213 }
214
215 //=================================================================================
216 // function : Init()
217 // purpose  :
218 //=================================================================================
219 void MeasureGUI_CheckSelfIntersectionsDlg::Init()
220 {
221   // Fill in the combo box.
222   myLevelBox->insertItem(GEOM::SI_V_V, tr("GEOM_CHECK_INTE_V_V"));
223   myLevelBox->insertItem(GEOM::SI_V_E, tr("GEOM_CHECK_INTE_V_E"));
224   myLevelBox->insertItem(GEOM::SI_E_E, tr("GEOM_CHECK_INTE_E_E"));
225   myLevelBox->insertItem(GEOM::SI_V_F, tr("GEOM_CHECK_INTE_V_F"));
226   myLevelBox->insertItem(GEOM::SI_E_F, tr("GEOM_CHECK_INTE_E_F"));
227   myLevelBox->insertItem(GEOM::SI_ALL, tr("GEOM_CHECK_INTE_ALL"));
228   myLevelBox->setCurrentIndex(GEOM::SI_ALL);
229   myComputeButton1->setEnabled(false);
230
231   connect(mySelButton1,        SIGNAL(clicked()),
232           this,               SLOT(SetEditCurrentArgument()));
233   connect(myInteList1,         SIGNAL(itemSelectionChanged()),
234           SLOT(onInteListSelectionChanged()));
235   connect(myShapeList1,        SIGNAL(itemSelectionChanged()),
236           SLOT(onSubShapesListSelectionChanged()));
237   connect(myLevelBox,         SIGNAL(currentIndexChanged(int)),
238           this,               SLOT(clear()));
239   connect(myComputeButton1,    SIGNAL(clicked()), this, SLOT(onCompute()));
240
241   /***************************************************************/
242   myObj2.nullify();
243   myEditObjName2->setText("");
244   myEditObjName2->setEnabled(true);
245
246   myDetGaps->setChecked(false);
247   initSpinBox(myTolerance, 0, MAX_NUMBER, 1);
248   myTolerance->setValue(0);
249   myTolerance->setEnabled(false);
250   myComputeButton2->setEnabled(false);
251
252   // Obtain deflection from preferences
253   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
254   initSpinBox(myDeflection, 1e-3, 1.0, 1e-3);
255   myDeflection->setValue(qMax(1e-3, resMgr->doubleValue("Geometry", "deflection_coeff", 1e-3)));
256
257   connect( mySelButton2,       SIGNAL(clicked()),
258           this,               SLOT(SetEditCurrentArgument()));
259   connect( myDetGaps,          SIGNAL(toggled(bool)), this, SLOT(OnGaps(bool))); 
260   connect( myTolerance,       SIGNAL(valueChanged(double)), this, SLOT(clear()));
261   connect( myDeflection,      SIGNAL(valueChanged(double)), this, SLOT(clear()));
262   connect( myInteList2,         SIGNAL(itemSelectionChanged()),
263           SLOT(onInteListSelectionChanged()));
264   connect( myShapeList2,       SIGNAL(itemSelectionChanged()),
265           SLOT(onSubShapesListSelectionChanged()));
266   connect( myComputeButton2,    SIGNAL(clicked()), this, SLOT(onCompute()));
267
268   /***************************************************************/
269
270   connect(this,               SIGNAL(constructorsClicked(int)), 
271           this,               SLOT(ConstructorsClicked(int)));
272   connect(myGeomGUI,          SIGNAL(SignalDeactivateActiveDialog()),
273           this,               SLOT(DeactivateActiveDialog()));
274   connect(myGeomGUI,          SIGNAL(SignalCloseAllDialogs()),
275           this,               SLOT(ClickOnCancel()));
276   connect(buttonOk(),         SIGNAL(clicked()), this, SLOT(ClickOnOk()));
277   connect(buttonApply(),      SIGNAL(clicked()), this, SLOT(ClickOnApply()));
278   LightApp_SelectionMgr* aSel = myGeomGUI->getApp()->selectionMgr();
279   connect(aSel,               SIGNAL(currentSelectionChanged()),
280           this,               SLOT(SelectionIntoArgument()));
281
282   initName( tr( "GEOM_SELF_INTERSECTION_NAME") );
283   buttonOk()->setEnabled(false);
284   buttonApply()->setEnabled(false);
285
286   ConstructorsClicked(0);
287
288   activateSelection();
289   SelectionIntoArgument();
290 }
291
292 //=================================================================================
293 // function : clear
294 // purpose  :
295 //=================================================================================
296 void MeasureGUI_CheckSelfIntersectionsDlg::clear()
297 {
298   getTextView()->setText("");
299   getComputeButton()->setEnabled(true);
300
301   getInteList()->blockSignals(true);
302   getShapeList()->blockSignals(true);
303   getInteList()->clear();
304   getShapeList()->clear();
305   getInteList()->blockSignals(false);
306   getShapeList()->blockSignals(false);
307
308   erasePreview();
309   buttonOk()->setEnabled(false);
310   buttonApply()->setEnabled(false);
311 }
312
313 //=================================================================================
314 // function : ConstructorsClicked()
315 // purpose  : Radio button management
316 //=================================================================================
317 void MeasureGUI_CheckSelfIntersectionsDlg::ConstructorsClicked(int constructorId)
318 {
319   if (myCurrConstrId == constructorId)
320     return;
321
322   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
323
324   switch (constructorId) {
325   case 0:
326     mySimpleGrp->show();
327     myFastGrp->hide();
328     break;
329   case 1:
330     mySimpleGrp->hide();
331     myFastGrp->show();
332     break;
333   }
334
335   myCurrConstrId = constructorId;
336
337   connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
338            this, SLOT(SelectionIntoArgument()));
339
340   qApp->processEvents();
341   updateGeometry();
342   resize(minimumSizeHint());
343
344   processPreview();
345   //updateButtonState();
346   activateSelection();
347   SelectionIntoArgument();
348 }
349
350 //=================================================================================
351 // function : onCompute
352 // purpose  :
353 //=================================================================================
354 void MeasureGUI_CheckSelfIntersectionsDlg::onCompute()
355 {
356   bool    hasSelfInte = false;
357   QString anErrMsg("");
358
359   if (!findSelfIntersections(hasSelfInte, anErrMsg)) {
360     getTextView()->setText(anErrMsg);
361     return;
362   }
363
364   // Status and apply buttons
365   QString aMsg("");
366
367   if (hasSelfInte) {
368     aMsg += tr("GEOM_SELF_INTERSECTIONS_FOUND");
369     buttonOk()->setEnabled(true);
370     buttonApply()->setEnabled(true);
371   } else {
372     aMsg += tr("GEOM_NO_SELF_INTERSECTIONS");
373   }
374
375   if (!anErrMsg.isEmpty()) {
376     aMsg += "\n\n";
377     aMsg += anErrMsg;
378   }
379
380   getTextView()->setText(aMsg);
381
382   // Pairs
383   QStringList anInteList;
384   QString anInteStr ("");
385   int nbPairs = getInters()->length()/2;
386
387   for (int i = 1; i <= nbPairs; i++) {
388     anInteStr = "Intersection # ";
389     anInteStr += QString::number(i);
390     anInteList.append(anInteStr);
391   }
392
393   getInteList()->addItems(anInteList);
394   getComputeButton()->setEnabled(false);
395 }
396
397 //=================================================================================
398 // function : ActivateThisDialog
399 // purpose  :
400 //=================================================================================
401 void MeasureGUI_CheckSelfIntersectionsDlg::ActivateThisDialog()
402 {
403   GEOMBase_Skeleton::ActivateThisDialog();
404
405   LightApp_SelectionMgr* aSel = myGeomGUI->getApp()->selectionMgr();
406   if ( aSel )
407     connect( aSel, SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) );
408
409   activateSelection();
410   DISPLAY_PREVIEW_MACRO
411 }
412
413 //=================================================================================
414 // function : DeactivateActiveDialog()
415 // purpose  : public slot to deactivate if active
416 //=================================================================================
417 void MeasureGUI_CheckSelfIntersectionsDlg::DeactivateActiveDialog()
418 {
419   GEOMBase_Skeleton::DeactivateActiveDialog();
420 }
421
422 //=================================================================================
423 // function : activateSelection
424 // purpose  : 
425 //=================================================================================
426 void MeasureGUI_CheckSelfIntersectionsDlg::activateSelection()
427 {
428   switch (getConstructorId()) {
429   case 0:
430     globalSelection(GEOM_ALLSHAPES);
431     break;
432   case 1:
433     TColStd_MapOfInteger aTypes;
434     aTypes.Add(GEOM_COMPOUND );
435     aTypes.Add(GEOM_SOLID );
436     aTypes.Add(GEOM_SHELL);
437     aTypes.Add(GEOM_FACE);
438     globalSelection(aTypes);
439
440     std::list<int> needTypes;
441     needTypes.push_back( TopAbs_FACE ), needTypes.push_back( TopAbs_SHELL ), needTypes.push_back( TopAbs_SOLID ), needTypes.push_back( TopAbs_COMPOUND );
442     localSelection( needTypes );
443     break;
444   }
445 }
446
447 //=================================================================================
448 // function : ClickOnOk()
449 // purpose  :
450 //=================================================================================
451 void MeasureGUI_CheckSelfIntersectionsDlg::ClickOnOk()
452 {
453   if ( ClickOnApply() )
454     ClickOnCancel();
455 }
456
457 //=================================================================================
458 // function : ClickOnApply()
459 // purpose  :
460 //=================================================================================
461 bool MeasureGUI_CheckSelfIntersectionsDlg::ClickOnApply()
462 {
463   if ( !onAccept() )
464     return false;
465
466   clear();
467   initName();
468
469   ConstructorsClicked(getConstructorId());
470
471   return true;
472 }
473
474 //=================================================================================
475 // function : extractPrefix
476 // purpose  :
477 //=================================================================================
478 bool MeasureGUI_CheckSelfIntersectionsDlg::extractPrefix() const
479 {
480   return true;
481 }
482
483 //=================================================================================
484 // function : createOperation
485 // purpose  :
486 //=================================================================================
487 GEOM::GEOM_IOperations_ptr MeasureGUI_CheckSelfIntersectionsDlg::createOperation()
488 {
489   return getGeomEngine()->GetIMeasureOperations();
490 }
491
492 //=================================================================================
493 // function : isValid
494 // purpose  :
495 //=================================================================================
496 bool MeasureGUI_CheckSelfIntersectionsDlg::isValid( QString& )
497 {
498   return !getObj().isNull();
499 }
500
501 //=================================================================================
502 // function : SetEditCurrentArgument
503 // purpose  :
504 //=================================================================================
505 void MeasureGUI_CheckSelfIntersectionsDlg::SetEditCurrentArgument()
506 {
507   getEditObjName()->setFocus();
508   SelectionIntoArgument();
509 }
510
511 //=================================================================================
512 // function : OnGaps()
513 // purpose  :
514 //=================================================================================
515 void MeasureGUI_CheckSelfIntersectionsDlg::OnGaps(bool checked)
516 {
517   clear();
518   myTolerance->setEnabled(checked);
519 }
520 //=================================================================================
521 // function : SelectionIntoArgument
522 // purpose  :
523 //=================================================================================
524 void MeasureGUI_CheckSelfIntersectionsDlg::SelectionIntoArgument()
525 {
526   QList<TopAbs_ShapeEnum> typesLst;
527
528   if ( getConstructorId() == 0 ) {
529     typesLst << TopAbs_COMPOUND
530              << TopAbs_COMPSOLID
531              << TopAbs_SOLID
532              << TopAbs_SHELL
533              << TopAbs_FACE
534              << TopAbs_WIRE
535              << TopAbs_EDGE
536              << TopAbs_VERTEX
537              << TopAbs_SHAPE;
538   } else {
539     typesLst << TopAbs_FACE
540              << TopAbs_SHELL
541              << TopAbs_SOLID
542              << TopAbs_COMPOUND;
543   }
544
545   // Clear the dialog.
546   clear();
547
548   GEOM::GeomObjPtr aSelectedObject = getSelected( typesLst );
549
550   (getConstructorId() == 0 ? myObj1 :myObj2) = aSelectedObject;
551   getEditObjName()->setText(getObj() ? GEOMBase::GetName(getObj().get()) : "");
552 }
553
554 //=================================================================================
555 // function : enterEvent
556 // purpose  :
557 //=================================================================================
558 void MeasureGUI_CheckSelfIntersectionsDlg::enterEvent(QEvent *)
559 {
560   if ( !mainFrame()->GroupConstructors->isEnabled() )
561     ActivateThisDialog();
562 }
563
564 //=================================================================================
565 // function : findSelfIntersections
566 // purpose  :
567 //=================================================================================
568 bool MeasureGUI_CheckSelfIntersectionsDlg::findSelfIntersections
569         (bool &HasSelfInte, QString &theErrMsg)
570 {
571   if (getObj()->_is_nil()) {
572     return false;
573   }
574
575   GEOM::GEOM_IMeasureOperations_var anOper =
576     GEOM::GEOM_IMeasureOperations::_narrow(getOperation());
577   bool isOK = true;
578   int  nbPairs  = 0;
579   int aLevel = myLevelBox->currentIndex();
580
581   SUIT_OverrideCursor wc;
582
583   try {
584     if ( getConstructorId() == 0 ) {
585       HasSelfInte = !anOper->CheckSelfIntersections(myObj1.get(), aLevel, myInters1);
586     } else {
587       HasSelfInte = !anOper->CheckSelfIntersectionsFast(myObj2.get(), getDeflection(), getTolerance(), myInters2);
588     }
589     nbPairs = getInters()->length()/2;
590
591     if (nbPairs*2 != (int)getInters()->length()) {
592       isOK = false;
593     }
594   }
595   catch (const SALOME::SALOME_Exception& e) {
596     SalomeApp_Tools::QtCatchCorbaException(e);
597     isOK = false;
598   }
599
600   if (!anOper->IsDone()) {
601     if (getInters()->length() == 0) {
602       theErrMsg = tr(anOper->GetErrorCode());
603       isOK = false;
604     } else {
605       // Valid case. Display all computed self-intersections
606       theErrMsg = tr("GEOM_CHECK_SELF_INTERSECTIONS_ERRORS");
607     }
608   } else if (!isOK) {
609     theErrMsg = tr("GEOM_CHECK_SELF_INTERSECTIONS_FAILED");
610   }
611
612   return isOK;
613 }
614
615 //=================================================================================
616 // function : onInteListSelectionChanged
617 // purpose  :
618 //=================================================================================
619 void MeasureGUI_CheckSelfIntersectionsDlg::onInteListSelectionChanged()
620 {
621   erasePreview();
622   getShapeList()->clear();
623
624   TopoDS_Shape aSelShape;
625   if (!getObj()->_is_nil() && GEOMBase::GetShape(getObj().get(), aSelShape)) {
626     TopTools_IndexedMapOfShape anIndices;
627     TopExp::MapShapes(aSelShape, anIndices);
628
629     int nbSelected = getInteList()->selectedItems().size();
630
631     for (int i = 0; i < getInteList()->count(); i++) {
632       if ( getInteList()->item(i)->isSelected() ) {
633         if ( nbSelected > 1 )
634           getShapeList()->addItem(QString("--- #%1 ---").arg(i+1));
635         for (int j = 0; j < 2; j++) {
636           TopoDS_Shape aSubShape = anIndices.FindKey(getInters()[i*2+j]);
637           QString aType = GEOMBase::GetShapeTypeString(aSubShape);
638           getShapeList()->addItem(QString("%1_%2").arg(aType).arg(getInters()[i*2+j]));
639           getShapeList()->item(getShapeList()->count()-1)->setData(Qt::UserRole, getInters()[i*2+j]);
640         }
641       }
642     }
643   }
644 }
645
646 //=================================================================================
647 // function : onSubShapesListSelectionChanged
648 // purpose  :
649 //=================================================================================
650 void MeasureGUI_CheckSelfIntersectionsDlg::onSubShapesListSelectionChanged()
651 {
652   erasePreview();
653
654   // Selected IDs
655   QList<QListWidgetItem*> selected = getShapeList()->selectedItems();
656   QList<int> aIds;
657   foreach(QListWidgetItem* item, selected) {
658     int idx = item->data(Qt::UserRole).toInt();
659     if (idx > 0 && aIds.indexOf(idx) < 0) aIds.append(idx);
660   }
661
662   if (aIds.empty()) return;
663
664   TopoDS_Shape aSelShape;
665   TopoDS_Shape aSubShape;
666   TopTools_IndexedMapOfShape anIndices;
667   if (!getObj()->_is_nil() && GEOMBase::GetShape(getObj().get(), aSelShape)) {
668     TopExp::MapShapes(aSelShape, anIndices);
669     getDisplayer()->SetColor(Quantity_NOC_RED);
670     getDisplayer()->SetWidth(3);
671     getDisplayer()->SetToActivate(false);
672     foreach(int idx, aIds) {
673       aSubShape = anIndices.FindKey(idx);
674       try {
675         SALOME_Prs* aPrs = !aSubShape.IsNull() ? getDisplayer()->BuildPrs(aSubShape) : 0;
676         if (aPrs) displayPreview(aPrs, true);
677       }
678       catch (const SALOME::SALOME_Exception& e) {
679         SalomeApp_Tools::QtCatchCorbaException(e);
680       }
681     }
682   }
683 }
684
685 //=================================================================================
686 // function : execute
687 // purpose  :
688 //=================================================================================
689 bool MeasureGUI_CheckSelfIntersectionsDlg::execute(ObjectList& objects)
690 {
691   bool hasSelfInte;
692   QString anErrMsg;
693
694   if (!findSelfIntersections(hasSelfInte, anErrMsg)) {
695     return false;
696   }
697
698   TColStd_IndexedMapOfInteger aMapIndex;
699   QList<int> pairs;
700
701   int nbSelected = getInteList()->selectedItems().size();
702
703   // Collect the map of indices
704   for (int i = 0; i < getInteList()->count(); i++) {
705     if ( nbSelected < 1 || getInteList()->item(i)->isSelected() ) {
706       aMapIndex.Add(getInters()[i*2]);
707       aMapIndex.Add(getInters()[i*2 + 1]);
708       pairs << getInters()[i*2];
709       pairs << getInters()[i*2 + 1];
710     }
711   }
712
713   GEOM::ShapesOpPtr shapesOper = getGeomEngine()->GetIShapesOperations();
714   
715   // Explode sub-shapes
716   GEOM::ListOfLong_var anArray   = new GEOM::ListOfLong;
717   anArray->length(aMapIndex.Extent());
718
719   for (int i = 1; i <= aMapIndex.Extent(); i++)
720     anArray[i-1] = aMapIndex.FindKey(i);
721
722   GEOM::ListOfGO_var aList = shapesOper->MakeSubShapes(getObj().get(), anArray);
723
724   // Make compounds
725   for (int i = 0; i < pairs.count()/2; i++) {
726     GEOM::ListOfGO_var aPair = new GEOM::ListOfGO();
727     aPair->length(2);
728     aPair[0] = aList[ aMapIndex.FindIndex(pairs[i*2]) - 1 ];
729     aPair[1] = aList[ aMapIndex.FindIndex(pairs[i*2+1]) - 1 ];
730     GEOM::GEOM_Object_var aCompound = shapesOper->MakeCompound( aPair );
731     objects.push_back(aCompound._retn());
732   }
733
734   return true;
735 }
736
737 //=================================================================================
738 // function : getDeflection
739 // purpose  :
740 //=================================================================================
741 float MeasureGUI_CheckSelfIntersectionsDlg::getDeflection()
742 {
743   return (float)myDeflection->value();
744 }
745
746 //=================================================================================
747 // function : getTolerance
748 // purpose  :
749 //=================================================================================
750 double MeasureGUI_CheckSelfIntersectionsDlg::getTolerance()
751 {
752   double aVal = myTolerance->value();
753   if (!myDetGaps->isChecked() || aVal < 0.0)
754     return 0.0;
755   return aVal;
756 }
757
758 //================================================================
759 // Function : getFather
760 // Purpose  : Get father object for object to be added in study
761 //            (called with addInStudy method)
762 //================================================================
763 GEOM::GEOM_Object_ptr MeasureGUI_CheckSelfIntersectionsDlg::getFather
764                   (GEOM::GEOM_Object_ptr)
765 {
766   return getObj().get();
767 }
768
769 //=================================================================================
770 // function : getSourceObjects
771 // purpose  : virtual method to get source objects
772 //=================================================================================
773 QList<GEOM::GeomObjPtr> MeasureGUI_CheckSelfIntersectionsDlg::getSourceObjects()
774 {
775   QList<GEOM::GeomObjPtr> res;
776   res << getObj();
777   return res;
778 }
779
780 //=================================================================================
781 // GETTERS
782 //=================================================================================
783 QTextBrowser* MeasureGUI_CheckSelfIntersectionsDlg::getTextView()
784 {
785   return ( getConstructorId() == 0 ? myTextView1 : myTextView2 );
786 }
787
788 QListWidget* MeasureGUI_CheckSelfIntersectionsDlg::getInteList()
789 {
790   return ( getConstructorId() == 0 ? myInteList1 : myInteList2 );
791 }
792
793 QListWidget* MeasureGUI_CheckSelfIntersectionsDlg::getShapeList()
794 {
795   return ( getConstructorId() == 0 ? myShapeList1 : myShapeList2 );
796 }
797
798 QPushButton* MeasureGUI_CheckSelfIntersectionsDlg::getComputeButton()
799 {
800   return ( getConstructorId() == 0 ? myComputeButton1 : myComputeButton2 );
801 }
802
803 QLineEdit* MeasureGUI_CheckSelfIntersectionsDlg::getEditObjName()
804 {
805   return ( getConstructorId() == 0 ? myEditObjName1 : myEditObjName2 );
806 }
807
808 GEOM::GeomObjPtr MeasureGUI_CheckSelfIntersectionsDlg::getObj()
809 {
810   return ( getConstructorId() == 0 ? myObj1 : myObj2 );
811 }
812
813 GEOM::ListOfLong_var MeasureGUI_CheckSelfIntersectionsDlg::getInters()
814 {
815   return ( getConstructorId() == 0 ? myInters1 : myInters2 );
816 }