Salome HOME
Fix usage of SUIT_OverrideCursor
[modules/geom.git] / src / MeasureGUI / MeasureGUI_CheckSelfIntersectionsDlg.cxx
1 // Copyright (C) 2007-2015  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_OverrideCursor.h>
30 #include <SUIT_Session.h>
31 #include <SUIT_ResourceMgr.h>
32 #include <LightApp_SelectionMgr.h>
33 #include <SalomeApp_Tools.h>
34 #include <SalomeApp_Application.h>
35
36 #include <TopTools_IndexedMapOfShape.hxx>
37 #include <TopExp.hxx>
38 #include <TColStd_IndexedMapOfInteger.hxx>
39 #include <TColStd_MapOfInteger.hxx>
40
41 #include <DlgRef.h>
42 #include <GeometryGUI.h>
43 #include <GEOMBase.h>
44 #include <GEOMImpl_Types.hxx>
45 #include <GEOM_GenericObjPtr.h>
46
47 #include <QListWidget>
48
49 #define TEXTEDIT_FONT_FAMILY "Courier"
50 #define TEXTEDIT_FONT_SIZE 11
51
52 //=================================================================================
53 // class    : MeasureGUI_CheckSelfIntersectionsDlg()
54 // purpose  : Constructs a MeasureGUI_CheckSelfIntersectionsDlg which is a child of 'parent', with the
55 //            name 'name' and widget flags set to 'f'.
56 //            The dialog will by default be modeless, unless you set 'modal' to
57 //            true to construct a modal dialog.
58 //=================================================================================
59 MeasureGUI_CheckSelfIntersectionsDlg::MeasureGUI_CheckSelfIntersectionsDlg (GeometryGUI* GUI, QWidget* parent)
60   : GEOMBase_Skeleton (GUI, parent, false),
61     myTextView        (0),
62     mySelButton       (0),
63     myEditObjName     (0),
64     myLevelBox        (0),
65     myComputeButton   (0),
66     myInteList        (0),
67     myShapeList       (0)
68 {
69   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
70   QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_CHECK_SELF_INTERSECTIONS")));
71   QPixmap image1 (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT")));
72
73   setWindowTitle(tr("GEOM_CHECK_SELF_INTERSECTIONS"));
74
75   /***************************************************************/
76   mainFrame()->GroupConstructors->setTitle(tr("GEOM_CHECK_SELF_INTERSECTIONS"));
77   mainFrame()->RadioButton1->setIcon(image0);
78   mainFrame()->RadioButton2->setAttribute( Qt::WA_DeleteOnClose );
79   mainFrame()->RadioButton2->close();
80   mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose );
81   mainFrame()->RadioButton3->close();
82
83   QGroupBox *aGrp      = new QGroupBox(tr("GEOM_CHECK_INFOS"));
84   QLabel    *anObjLbl  = new QLabel(tr("GEOM_OBJECT"));
85   QLabel    *anInteLbl = new QLabel(tr("GEOM_CHECK_INTE_INTERSECTIONS"));
86   QLabel    *aShapeLbl = new QLabel(tr("GEOM_CHECK_INTE_SUBSHAPES"));
87   QLabel    *aLevelLbl = new QLabel(tr("GEOM_CHECK_INTE_CHECK_LEVEL"));
88   QLabel    *aSummaryLbl = new QLabel(tr("GEOM_CHECK_INTE_SUMMARY"));
89   QFont      aFont (TEXTEDIT_FONT_FAMILY, TEXTEDIT_FONT_SIZE);
90
91   aFont.setStyleHint(QFont::TypeWriter, QFont::PreferAntialias);
92   myTextView = new QTextBrowser;
93   myTextView->setReadOnly(true);
94   myTextView->setFont(aFont);
95
96   mySelButton = new QPushButton;
97   mySelButton->setIcon(image1);
98   mySelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
99
100   myEditObjName = new QLineEdit;
101   myEditObjName->setReadOnly(true);
102
103   myLevelBox = new QComboBox;
104
105   myComputeButton = new QPushButton(tr("GEOM_CHECK_INTE_COMPUTE"));
106
107
108   myInteList  = new QListWidget;
109   myInteList->setSelectionMode(QAbstractItemView::ExtendedSelection);
110   myShapeList = new QListWidget;
111   myShapeList->setSelectionMode(QAbstractItemView::ExtendedSelection);
112
113   QGridLayout *aGrpLayout = new QGridLayout(aGrp);
114
115   aGrpLayout->setMargin(9);
116   aGrpLayout->setSpacing(6);
117   aGrpLayout->addWidget(anObjLbl,        0, 0);
118   aGrpLayout->addWidget(anInteLbl,       5, 0);
119   aGrpLayout->addWidget(aShapeLbl,       5, 2);
120   aGrpLayout->addWidget(aLevelLbl,       1, 0);
121   aGrpLayout->addWidget(myLevelBox,      1, 1, 1, 2);
122   aGrpLayout->addWidget(myComputeButton, 2, 0, 1, 3);
123   aGrpLayout->addWidget(aSummaryLbl,     3, 0);
124   aGrpLayout->addWidget(myTextView,      4, 0, 1, 3);
125   aGrpLayout->addWidget(mySelButton,     0, 1);
126   aGrpLayout->addWidget(myEditObjName,   0, 2);
127   aGrpLayout->addWidget(myInteList,      6, 0, 1, 2);
128   aGrpLayout->addWidget(myShapeList,     6, 2);
129
130   QVBoxLayout* layout = new QVBoxLayout (centralWidget());
131   layout->setMargin(0); layout->setSpacing(6);
132   layout->addWidget(aGrp);
133
134   /***************************************************************/
135
136   myHelpFileName = "check_self_intersections_page.html";
137
138   /* Initialisation */
139   Init();
140 }
141
142 //=================================================================================
143 // function : ~MeasureGUI_CheckSelfIntersectionsDlg()
144 // purpose  : Destroys the object and frees any allocated resources
145 //=================================================================================
146 MeasureGUI_CheckSelfIntersectionsDlg::~MeasureGUI_CheckSelfIntersectionsDlg()
147 {
148 }
149
150 //=================================================================================
151 // function : Init()
152 // purpose  :
153 //=================================================================================
154 void MeasureGUI_CheckSelfIntersectionsDlg::Init()
155 {
156   // Fill in the combo box.
157   myLevelBox->insertItem(GEOM::SI_V_V, tr("GEOM_CHECK_INTE_V_V"));
158   myLevelBox->insertItem(GEOM::SI_V_E, tr("GEOM_CHECK_INTE_V_E"));
159   myLevelBox->insertItem(GEOM::SI_E_E, tr("GEOM_CHECK_INTE_E_E"));
160   myLevelBox->insertItem(GEOM::SI_V_F, tr("GEOM_CHECK_INTE_V_F"));
161   myLevelBox->insertItem(GEOM::SI_E_F, tr("GEOM_CHECK_INTE_E_F"));
162   myLevelBox->insertItem(GEOM::SI_ALL, tr("GEOM_CHECK_INTE_ALL"));
163   myLevelBox->setCurrentIndex(GEOM::SI_ALL);
164
165   connect(myGeomGUI,          SIGNAL(SignalDeactivateActiveDialog()),
166           this,               SLOT(DeactivateActiveDialog()));
167   connect(myGeomGUI,          SIGNAL(SignalCloseAllDialogs()),
168           this,               SLOT(ClickOnCancel()));
169   connect(buttonOk(),         SIGNAL(clicked()), this, SLOT(ClickOnOk()));
170   connect(buttonApply(),      SIGNAL(clicked()), this, SLOT(ClickOnApply()));
171   connect(mySelButton,        SIGNAL(clicked()),
172           this,               SLOT(SetEditCurrentArgument()));
173   connect(myInteList,         SIGNAL(itemSelectionChanged()),
174           SLOT(onInteListSelectionChanged()));
175   connect(myShapeList,        SIGNAL(itemSelectionChanged()),
176           SLOT(onSubShapesListSelectionChanged()));
177   connect(myLevelBox,         SIGNAL(currentIndexChanged(int)),
178           this,               SLOT(clear()));
179   connect(myComputeButton,    SIGNAL(clicked()), this, SLOT(onCompute()));
180
181   LightApp_SelectionMgr* aSel = myGeomGUI->getApp()->selectionMgr();
182
183   connect(aSel,               SIGNAL(currentSelectionChanged()),
184           this,               SLOT(SelectionIntoArgument()));
185
186   initName( tr( "GEOM_SELF_INTERSECTION_NAME") );
187   buttonOk()->setEnabled(false);
188   buttonApply()->setEnabled(false);
189   myComputeButton->setEnabled(false);
190   activateSelection();
191   SelectionIntoArgument();
192 }
193
194 //=================================================================================
195 // function : clear
196 // purpose  :
197 //=================================================================================
198 void MeasureGUI_CheckSelfIntersectionsDlg::clear()
199 {
200   myTextView->setText("");
201
202   myInteList->blockSignals(true);
203   myShapeList->blockSignals(true);
204   myInteList->clear();
205   myShapeList->clear();
206   myInteList->blockSignals(false);
207   myShapeList->blockSignals(false);
208
209   erasePreview();
210
211   buttonOk()->setEnabled(false);
212   buttonApply()->setEnabled(false);
213   myComputeButton->setEnabled(true);
214 }
215
216 //=================================================================================
217 // function : onCompute
218 // purpose  :
219 //=================================================================================
220 void MeasureGUI_CheckSelfIntersectionsDlg::onCompute()
221 {
222   bool    hasSelfInte = false;
223   QString anErrMsg("");
224
225   if (!findSelfIntersections(hasSelfInte, anErrMsg)) {
226     myTextView->setText(anErrMsg);
227     return;
228   }
229
230   // Status and apply buttons
231   QString aMsg("");
232
233   if (hasSelfInte) {
234     aMsg += tr("GEOM_SELF_INTERSECTIONS_FOUND");
235     buttonOk()->setEnabled(true);
236     buttonApply()->setEnabled(true);
237   } else {
238     aMsg += tr("GEOM_NO_SELF_INTERSECTIONS");
239   }
240
241   if (!anErrMsg.isEmpty()) {
242     aMsg += "\n\n";
243     aMsg += anErrMsg;
244   }
245
246   myTextView->setText(aMsg);
247
248   // Pairs
249   QStringList anInteList;
250   QString anInteStr ("");
251   int nbPairs = myInters->length()/2;
252
253   for (int i = 1; i <= nbPairs; i++) {
254     anInteStr = "Intersection # ";
255     anInteStr += QString::number(i);
256     anInteList.append(anInteStr);
257   }
258
259   myInteList->addItems(anInteList);
260   myComputeButton->setEnabled(false);
261 }
262
263 //=================================================================================
264 // function : ActivateThisDialog
265 // purpose  :
266 //=================================================================================
267 void MeasureGUI_CheckSelfIntersectionsDlg::ActivateThisDialog()
268 {
269   GEOMBase_Skeleton::ActivateThisDialog();
270
271   LightApp_SelectionMgr* aSel = myGeomGUI->getApp()->selectionMgr();
272   if ( aSel )
273     connect( aSel, SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) );
274
275   activateSelection();
276   DISPLAY_PREVIEW_MACRO
277 }
278
279 //=================================================================================
280 // function : DeactivateActiveDialog()
281 // purpose  : public slot to deactivate if active
282 //=================================================================================
283 void MeasureGUI_CheckSelfIntersectionsDlg::DeactivateActiveDialog()
284 {
285   GEOMBase_Skeleton::DeactivateActiveDialog();
286 }
287
288 //=================================================================================
289 // function : activateSelection
290 // purpose  : 
291 //=================================================================================
292 void MeasureGUI_CheckSelfIntersectionsDlg::activateSelection()
293 {
294   globalSelection(GEOM_ALLSHAPES);
295 }
296
297 //=================================================================================
298 // function : ClickOnOk()
299 // purpose  :
300 //=================================================================================
301 void MeasureGUI_CheckSelfIntersectionsDlg::ClickOnOk()
302 {
303   if ( ClickOnApply() )
304     ClickOnCancel();
305 }
306
307 //=================================================================================
308 // function : ClickOnApply()
309 // purpose  :
310 //=================================================================================
311 bool MeasureGUI_CheckSelfIntersectionsDlg::ClickOnApply()
312 {
313   if ( !onAccept() )
314     return false;
315
316   initName();
317   return true;
318 }
319
320 //=================================================================================
321 // function : extractPrefix
322 // purpose  :
323 //=================================================================================
324 bool MeasureGUI_CheckSelfIntersectionsDlg::extractPrefix() const
325 {
326   return true;
327 }
328
329 //=================================================================================
330 // function : createOperation
331 // purpose  :
332 //=================================================================================
333 GEOM::GEOM_IOperations_ptr MeasureGUI_CheckSelfIntersectionsDlg::createOperation()
334 {
335   return getGeomEngine()->GetIMeasureOperations( getStudyId() );
336 }
337
338 //=================================================================================
339 // function : isValid
340 // purpose  :
341 //=================================================================================
342 bool MeasureGUI_CheckSelfIntersectionsDlg::isValid( QString& )
343 {
344   return !myObj->_is_nil();
345 }
346
347 //=================================================================================
348 // function : SetEditCurrentArgument
349 // purpose  :
350 //=================================================================================
351 void MeasureGUI_CheckSelfIntersectionsDlg::SetEditCurrentArgument()
352 {
353   myEditObjName->setFocus();
354   SelectionIntoArgument();
355 }
356
357 //=================================================================================
358 // function : SelectionIntoArgument
359 // purpose  :
360 //=================================================================================
361 void MeasureGUI_CheckSelfIntersectionsDlg::SelectionIntoArgument()
362 {
363   // Clear the dialog.
364   clear();
365   myObj = GEOM::GEOM_Object::_nil();
366
367   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
368   SALOME_ListIO aSelList;
369   aSelMgr->selectedObjects(aSelList);
370
371   GEOM::GEOM_Object_var aSelectedObject = GEOM::GEOM_Object::_nil();
372
373   if (aSelList.Extent() > 0) {
374     aSelectedObject = GEOMBase::ConvertIOinGEOMObject( aSelList.First() );
375   }
376
377   if (aSelectedObject->_is_nil()) {
378     myEditObjName->setText("");
379     return;
380   }
381
382   myObj = aSelectedObject;
383   myEditObjName->setText(GEOMBase::GetName(myObj));
384 }
385
386 //=================================================================================
387 // function : enterEvent
388 // purpose  :
389 //=================================================================================
390 void MeasureGUI_CheckSelfIntersectionsDlg::enterEvent(QEvent *)
391 {
392   if ( !mainFrame()->GroupConstructors->isEnabled() )
393     ActivateThisDialog();
394 }
395
396 //=================================================================================
397 // function : findSelfIntersections
398 // purpose  :
399 //=================================================================================
400 bool MeasureGUI_CheckSelfIntersectionsDlg::findSelfIntersections
401         (bool &HasSelfInte, QString &theErrMsg)
402 {
403   if (myObj->_is_nil()) {
404     return false;
405   }
406
407   GEOM::GEOM_IMeasureOperations_var anOper =
408     GEOM::GEOM_IMeasureOperations::_narrow(getOperation());
409   bool isOK = true;
410   int  nbPairs  = 0;
411   int aLevel = myLevelBox->currentIndex();
412
413   SUIT_OverrideCursor wc;
414
415   try {
416     HasSelfInte = !anOper->CheckSelfIntersections(myObj, aLevel, myInters);
417     nbPairs = myInters->length()/2;
418
419     if (nbPairs*2 != myInters->length()) {
420       isOK = false;
421     }
422   }
423   catch (const SALOME::SALOME_Exception& e) {
424     SalomeApp_Tools::QtCatchCorbaException(e);
425     isOK = false;
426   }
427
428   if (!anOper->IsDone()) {
429     if (myInters->length() == 0) {
430       theErrMsg = tr(anOper->GetErrorCode());
431       isOK = false;
432     } else {
433       // Valid case. Display all computed self-intersections
434       theErrMsg = tr("GEOM_CHECK_SELF_INTERSECTIONS_ERRORS");
435     }
436   } else if (!isOK) {
437     theErrMsg = tr("GEOM_CHECK_SELF_INTERSECTIONS_FAILED");
438   }
439
440   return isOK;
441 }
442
443 //=================================================================================
444 // function : onInteListSelectionChanged
445 // purpose  :
446 //=================================================================================
447 void MeasureGUI_CheckSelfIntersectionsDlg::onInteListSelectionChanged()
448 {
449   erasePreview();
450   myShapeList->clear();
451
452   TopoDS_Shape aSelShape;
453   if (!myObj->_is_nil() && GEOMBase::GetShape(myObj, aSelShape)) {
454     TopTools_IndexedMapOfShape anIndices;
455     TopExp::MapShapes(aSelShape, anIndices);
456
457     int nbSelected = myInteList->selectedItems().size();
458
459     for (int i = 0; i < myInteList->count(); i++) {
460       if ( myInteList->item(i)->isSelected() ) {
461         if ( nbSelected > 1 )
462           myShapeList->addItem(QString("--- #%1 ---").arg(i+1));
463         for (int j = 0; j < 2; j++) {
464           TopoDS_Shape aSubShape = anIndices.FindKey(myInters[i*2+j]);
465           QString aType = GEOMBase::GetShapeTypeString(aSubShape);
466           myShapeList->addItem(QString("%1_%2").arg(aType).arg(myInters[i*2+j]));
467           myShapeList->item(myShapeList->count()-1)->setData(Qt::UserRole, myInters[i*2+j]);
468         }
469       }
470     }
471   }
472 }
473
474 //=================================================================================
475 // function : onSubShapesListSelectionChanged
476 // purpose  :
477 //=================================================================================
478 void MeasureGUI_CheckSelfIntersectionsDlg::onSubShapesListSelectionChanged()
479 {
480   erasePreview();
481
482   // Selected IDs
483   QList<QListWidgetItem*> selected = myShapeList->selectedItems();
484   QList<int> aIds;
485   foreach(QListWidgetItem* item, selected) {
486     int idx = item->data(Qt::UserRole).toInt();
487     if (idx > 0 && aIds.indexOf(idx) < 0) aIds.append(idx);
488   }
489
490   if (aIds.empty()) return;
491
492   TopoDS_Shape aSelShape;
493   TopoDS_Shape aSubShape;
494   TopTools_IndexedMapOfShape anIndices;
495   if (!myObj->_is_nil() && GEOMBase::GetShape(myObj, aSelShape)) {
496     TopExp::MapShapes(aSelShape, anIndices);
497     getDisplayer()->SetColor(Quantity_NOC_RED);
498     getDisplayer()->SetWidth(3);
499     getDisplayer()->SetToActivate(false);
500     foreach(int idx, aIds) {
501       aSubShape = anIndices.FindKey(idx);
502       try {
503         SALOME_Prs* aPrs = !aSubShape.IsNull() ? getDisplayer()->BuildPrs(aSubShape) : 0;
504         if (aPrs) displayPreview(aPrs, true);
505       }
506       catch (const SALOME::SALOME_Exception& e) {
507         SalomeApp_Tools::QtCatchCorbaException(e);
508       }
509     }
510   }
511 }
512
513 //=================================================================================
514 // function : execute
515 // purpose  :
516 //=================================================================================
517 bool MeasureGUI_CheckSelfIntersectionsDlg::execute(ObjectList& objects)
518 {
519   bool hasSelfInte;
520   QString anErrMsg;
521
522   if (!findSelfIntersections(hasSelfInte, anErrMsg)) {
523     return false;
524   }
525
526   TColStd_IndexedMapOfInteger aMapIndex;
527   QList<int> pairs;
528
529   int nbSelected = myInteList->selectedItems().size();
530
531   // Collect the map of indices
532   for (int i = 0; i < myInteList->count(); i++) {
533     if ( nbSelected < 1 || myInteList->item(i)->isSelected() ) {
534       aMapIndex.Add(myInters[i*2]);
535       aMapIndex.Add(myInters[i*2 + 1]);
536       pairs << myInters[i*2];
537       pairs << myInters[i*2 + 1];
538     }
539   }
540
541   GEOM::ShapesOpPtr shapesOper = getGeomEngine()->GetIShapesOperations(getStudyId());
542   
543   // Explode sub-shapes
544   GEOM::ListOfLong_var anArray   = new GEOM::ListOfLong;
545   anArray->length(aMapIndex.Extent());
546
547   for (int i = 1; i <= aMapIndex.Extent(); i++)
548     anArray[i-1] = aMapIndex.FindKey(i);
549
550   GEOM::ListOfGO_var aList = shapesOper->MakeSubShapes(myObj, anArray);
551
552   // Make compounds
553   for (int i = 0; i < pairs.count()/2; i++) {
554     GEOM::ListOfGO_var aPair = new GEOM::ListOfGO();
555     aPair->length(2);
556     aPair[0] = aList[ aMapIndex.FindIndex(pairs[i*2]) - 1 ];
557     aPair[1] = aList[ aMapIndex.FindIndex(pairs[i*2+1]) - 1 ];
558     GEOM::GEOM_Object_var aCompound = shapesOper->MakeCompound( aPair );
559     objects.push_back(aCompound._retn());
560   }
561
562   return true;
563 }
564
565 //================================================================
566 // Function : getFather
567 // Purpose  : Get father object for object to be added in study
568 //            (called with addInStudy method)
569 //================================================================
570 GEOM::GEOM_Object_ptr MeasureGUI_CheckSelfIntersectionsDlg::getFather
571                   (GEOM::GEOM_Object_ptr)
572 {
573   return myObj;
574 }