Salome HOME
085028ce12a02984a2b90971e09b9902d2360cbb
[modules/geom.git] / src / EntityGUI / EntityGUI_SubShapeDlg.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   : EntityGUI_SubShapeDlg.cxx
25 // Author : Lucien PIGNOLONI, Open CASCADE S.A.S.
26
27 #include "EntityGUI_SubShapeDlg.h"
28
29 #include <DlgRef.h>
30 #include <GeometryGUI.h>
31 #include <GEOMBase.h>
32 #include <GEOMUtils.hxx>
33 #ifndef DISABLE_PLOT2DVIEWER
34   #include <MeasureGUI_ShapeStatisticsDlg.h>
35 #endif
36
37 #include <OCCViewer_ViewModel.h>
38 #include <SVTK_ViewModel.h>
39 #include <SalomeApp_Study.h>
40 #include <SalomeApp_Application.h>
41 #include <LightApp_SelectionMgr.h>
42 #include <SALOME_ListIO.hxx>
43 #include <SUIT_MessageBox.h>
44
45 #include <SUIT_Desktop.h>
46 #include <SUIT_ResourceMgr.h>
47 #include <SUIT_Session.h>
48 #include <SUIT_ViewManager.h>
49 #include <SUIT_ViewWindow.h>
50
51 #include <TopExp.hxx>
52 #include <TopExp_Explorer.hxx>
53 #include <TopoDS_Iterator.hxx>
54 #include <TopTools_MapOfShape.hxx>
55 #include <TopTools_IndexedMapOfShape.hxx>
56
57 #include <TColStd_IndexedMapOfInteger.hxx>
58
59 #include <GEOMImpl_Types.hxx>
60
61 namespace
62 {
63   const char* const ShapeTypes [] = {
64     "Compound",
65     "Compsolid",
66     "Solid",
67     "Shell",
68     "Face",
69     "Wire",
70     "Edge",
71     "Vertex",
72     "Shape",
73     "Flat"
74   };
75
76   enum { Filter_LT, Filter_LE, Filter_GT, Filter_GE };
77
78   unsigned int NumberOfSubShapes(const TopoDS_Shape& S, const int shapeType, TopTools_MapOfShape& M)
79   {
80     unsigned int index = 0;
81
82     if (!S.IsNull()) {
83       if (S.ShapeType() == TopAbs_COMPOUND &&
84           (shapeType == TopAbs_SHAPE || shapeType == TopAbs_FLAT || shapeType == TopAbs_COMPOUND)) {
85         TopoDS_Iterator It(S, Standard_True, Standard_True);
86         for (; It.More(); It.Next()) {
87           TopoDS_Shape SS = It.Value();
88           if (M.Add(SS)) {
89             if (shapeType == TopAbs_FLAT) {
90               if (SS.ShapeType() != TopAbs_COMPOUND)
91                 index++;
92               else
93                 index += NumberOfSubShapes(SS, shapeType, M);
94             }
95             else if (shapeType == TopAbs_SHAPE || shapeType == SS.ShapeType()) {
96               index++;
97             }
98           }
99         }
100       }
101       else {
102         TopExp_Explorer Exp (S, TopAbs_ShapeEnum(shapeType));
103         for (; Exp.More(); Exp.Next()) {
104           if (M.Add(Exp.Current())) {
105             index++;
106           }
107         }
108       }
109     }
110     return index;
111   }
112   unsigned int NumberOfSubShapes(const TopoDS_Shape& S, const int shapeType)
113   {
114     TopTools_MapOfShape M;
115     return NumberOfSubShapes(S, shapeType, M);
116   }
117 }
118
119 //=================================================================================
120 // class    : EntityGUI_SubShapeDlg
121 // purpose  : Constructs a EntityGUI_SubShapeDlg which is a child of 'parent', with the
122 //            name 'name' and widget flags set to 'f'.
123 //            The dialog will by default be modeless, unless you set 'modal' to
124 //            TRUE to construct a modal dialog.
125 //=================================================================================
126 EntityGUI_SubShapeDlg::EntityGUI_SubShapeDlg(GeometryGUI* theGeometryGUI, QWidget* parent,
127                                               bool modal, Qt::WindowFlags fl)
128   : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl),
129     myDmMode( -1 ),
130     myIsHiddenMain(false)
131 {
132   QPixmap image0(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_SUBSHAPE")));
133   QPixmap image1(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT")));
134
135   setWindowTitle(tr("GEOM_SUBSHAPE_TITLE"));
136
137   /***************************************************************/
138   mainFrame()->GroupConstructors->setTitle(tr("GEOM_SUB_SHAPE"));
139   mainFrame()->RadioButton1->setIcon(image0);
140   mainFrame()->RadioButton2->setAttribute(Qt::WA_DeleteOnClose);
141   mainFrame()->RadioButton2->close();
142   mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
143   mainFrame()->RadioButton3->close();
144
145   GroupPoints = new DlgRef_1Sel1List1Check3Btn(centralWidget());
146
147   GroupPoints->GroupBox1->setTitle(tr("GEOM_ARGUMENTS"));
148   GroupPoints->TextLabel1->setText(tr("GEOM_MAIN_OBJECT"));
149   GroupPoints->TextLabel2->setText(tr("GEOM_SUBSHAPE_TYPE"));
150   GroupPoints->CheckButton1->setText(tr("GEOM_SUBSHAPE_SELECT"));
151   GroupPoints->PushButton1->setIcon(image1);
152   GroupPoints->PushButton2->setText(tr("SHOW_ONLY_SELECTED"));
153   GroupPoints->PushButton3->setText(tr("HIDE_SELECTED"));
154   GroupPoints->PushButton4->setText(tr("SHOW_ALL_SUB_SHAPES"));
155   GroupPoints->LineEdit1->setReadOnly(true);
156
157   //filter group
158
159   myFilterGrp = new QGroupBox(tr("GEOM_FILTER"), centralWidget());
160   myLessFilterCheck = new QCheckBox(myFilterGrp);
161   myLessFilterCombo = new QComboBox(myFilterGrp);
162   myLessFilterCombo->addItem( tr("GEOM_LESS_THAN"), Filter_LT );
163   myLessFilterCombo->addItem( tr("GEOM_LESSOREQUAL_THAN"), Filter_LE );
164   myGreaterFilterCheck = new QCheckBox(myFilterGrp);
165   myGreaterFilterCombo = new QComboBox(myFilterGrp);
166   myGreaterFilterCombo->addItem( tr("GEOM_GREAT_THAN"), Filter_GT );
167   myGreaterFilterCombo->addItem( tr("GEOM_GREATOREQUAL_THAN"), Filter_GE );
168   myLessFilterSpin = new SalomeApp_DoubleSpinBox(myFilterGrp);
169   myGreaterFilterSpin = new SalomeApp_DoubleSpinBox(myFilterGrp);
170   myApplyFilterButton = new QPushButton(tr("GEOM_BUT_APPLY"), myFilterGrp);
171 #ifndef DISABLE_PLOT2DVIEWER
172   myPlotDistributionButton = new QPushButton(tr("GEOM_PLOT_DISTRIBUTION"), myFilterGrp);
173 #endif
174
175   QGridLayout* filterLayout = new QGridLayout(myFilterGrp);
176   filterLayout->addWidget(myLessFilterCheck,    0, 0);
177   filterLayout->addWidget(myLessFilterCombo,    0, 1);
178   filterLayout->addWidget(myLessFilterSpin,     0, 2);
179   filterLayout->addWidget(myGreaterFilterCheck, 1, 0);
180   filterLayout->addWidget(myGreaterFilterCombo, 1, 1);
181   filterLayout->addWidget(myGreaterFilterSpin,  1, 2);
182   filterLayout->addWidget(myApplyFilterButton,  0, 3);
183 #ifndef DISABLE_PLOT2DVIEWER
184   filterLayout->addWidget(myPlotDistributionButton,  1, 3);
185 #endif
186
187   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
188   layout->setMargin(0); layout->setSpacing(6);
189   layout->addWidget(GroupPoints);
190   layout->addWidget(myFilterGrp);
191   /***************************************************************/
192
193   setIsOptimizedBrowsing(true);
194
195   setHelpFileName("create_explode_page.html");
196
197   mainFrame()->GroupBoxName->hide();
198
199   Init();
200 }
201
202 //=================================================================================
203 // function : ~EntityGUI_SubShapeDlg()
204 // purpose  : Destroys the object and frees any allocated resources
205 //=================================================================================
206 EntityGUI_SubShapeDlg::~EntityGUI_SubShapeDlg()
207 {
208   if (myIsHiddenMain) {
209     GEOM_Displayer* aDisplayer = getDisplayer();
210     aDisplayer->Display(myObject);
211     myIsHiddenMain = false;
212   }
213   myDmMode = -1;
214 }
215
216 //=================================================================================
217 // function : Init()
218 // purpose  :
219 //=================================================================================
220 void EntityGUI_SubShapeDlg::Init()
221 {
222   // Get setting of step value from file configuration
223   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
224   double step = resMgr->doubleValue("Geometry", "SettingsGeomStep", 100);
225
226   // min, max, step and decimals for spin boxes
227   initSpinBox(myLessFilterSpin, 0., COORD_MAX, step, "length_precision" );
228   initSpinBox(myGreaterFilterSpin, 0., COORD_MAX, step, "length_precision" );
229   myLessFilterSpin->setValue( 0. );
230   myGreaterFilterSpin->setValue( 0. );
231
232   /* init variables */
233   myDmMode = -1;
234   myEditCurrentArgument = GroupPoints->LineEdit1;
235   myObject = GEOM::GEOM_Object::_nil();
236
237   /* type for sub-shape selection */
238   for ( int i = 0; i <= (int)GEOM::FLAT; i++ )
239     GroupPoints->ComboBox1->addItem(ShapeTypes[i], i);
240
241   if (SUIT_Session::session()->activeApplication()->desktop()->activeWindow()->getViewManager()->getType()
242       != OCCViewer_Viewer::Type())
243     GroupPoints->CheckButton1->setEnabled(false);
244
245   /* signals and slots connections */
246   connect(myGeomGUI, SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
247
248   connect(buttonOk(),    SIGNAL(clicked()), this, SLOT(ClickOnOk()));
249   connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
250
251   connect(GroupPoints->PushButton1,  SIGNAL(clicked()),       this, SLOT(SetEditCurrentArgument()));
252   connect(GroupPoints->LineEdit1,    SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
253
254   connect(GroupPoints->ComboBox1,    SIGNAL(activated(int)),    this, SLOT(ComboTextChanged()));
255   connect(GroupPoints->CheckButton1, SIGNAL(stateChanged(int)), this, SLOT(SubShapeToggled()));
256
257   connect(GroupPoints->PushButton2, SIGNAL(clicked()), this, SLOT(showOnlySelected()));
258   connect(GroupPoints->PushButton3, SIGNAL(clicked()), this, SLOT(showOnlySelected()));
259   connect(GroupPoints->PushButton4, SIGNAL(clicked()), this, SLOT(showOnlySelected()));
260
261   connect(myApplyFilterButton, SIGNAL(clicked()),         this, SLOT(ClickOnOkFilter()));
262 #ifndef DISABLE_PLOT2DVIEWER
263   connect(myPlotDistributionButton, SIGNAL(clicked()),    this, SLOT(ClickOnPlot()));
264 #endif
265   connect(myLessFilterCheck,   SIGNAL(stateChanged(int)), this, SLOT(MeasureToggled()));
266   connect(myGreaterFilterCheck,   SIGNAL(stateChanged(int)), this, SLOT(MeasureToggled()));
267
268   connect(myGeomGUI->getApp()->selectionMgr(),
269           SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
270
271   updateButtonState();
272   resize(100,100);
273   SelectionIntoArgument();
274   SubShapeToggled();
275   MeasureToggled();
276 }
277
278 //=================================================================================
279 // function : enterEvent()
280 // purpose  :
281 //=================================================================================
282 void EntityGUI_SubShapeDlg::enterEvent(QEvent*)
283 {
284   if (!mainFrame()->GroupConstructors->isEnabled())
285     ActivateThisDialog();
286 }
287
288 //=================================================================================
289 // function : ActivateThisDialog()
290 // purpose  :
291 //=================================================================================
292 void EntityGUI_SubShapeDlg::ActivateThisDialog()
293 {
294   GEOMBase_Skeleton::ActivateThisDialog();
295   connect(myGeomGUI->getApp()->selectionMgr(),
296            SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
297   SubShapeToggled();
298   updateButtonState();
299 }
300
301 //=================================================================================
302 //function : closeEvent
303 //purpose  : remove temporary geom object
304 //=================================================================================
305 void EntityGUI_SubShapeDlg::closeEvent(QCloseEvent* e)
306 {
307   erasePreview(true);
308   GEOMBase_Skeleton::closeEvent(e);
309 }
310
311 //=================================================================================
312 // function : ClickOnOk()
313 // purpose  :
314 //=================================================================================
315 void EntityGUI_SubShapeDlg::ClickOnOk()
316 {
317   setIsApplyAndClose(true);
318
319   SUIT_Session::session()->activeApplication()->putInfo("");
320
321   /* Explode all sub-shapes */
322   bool isOk = true;
323   if (isAllSubShapes()) {
324     /* More than 30 sub-shapes : ask confirmation */
325     unsigned int nb = NumberOfSubShapes(myShape, shapeType());
326     if (nb > 30) {
327       if (SUIT_MessageBox::question( this,
328                                      tr("GEOM_CONFIRM"),
329                                      tr("GEOM_CONFIRM_INFO").arg(nb),
330                                      tr("GEOM_BUT_EXPLODE"),
331                                      tr("GEOM_BUT_CANCEL") ) != 0 )
332         isOk = false;  /* aborted */
333     }
334   }
335
336   if (isOk)
337     isOk = onAccept( true, true, false );
338
339   if (isOk)
340     ClickOnCancel();
341 }
342
343 //=================================================================================
344 // function : ClickOnApply()
345 // purpose  :
346 //=================================================================================
347 bool EntityGUI_SubShapeDlg::ClickOnApply()
348 {
349   SUIT_Session::session()->activeApplication()->putInfo("");
350
351   /* Explode all sub-shapes */
352   if (isAllSubShapes()) {
353     /* More than 30 sub-shapes : ask confirmation */
354     unsigned int nb = NumberOfSubShapes(myShape, shapeType());
355     if (nb > 30) {
356       if (SUIT_MessageBox::question( this,
357                                      tr("GEOM_CONFIRM"),
358                                      tr("GEOM_CONFIRM_INFO").arg(nb),
359                                      tr("GEOM_BUT_EXPLODE"),
360                                      tr("GEOM_BUT_CANCEL") ) != 0 )
361         return false;  /* aborted */
362     }
363   }
364   
365   setIsDisableBrowsing( true );
366   bool isOk = onAccept( true, true, false );
367   setIsDisableBrowsing( false );
368
369   // restore selection, corresponding to current selection mode
370   SubShapeToggled();
371
372   return isOk;
373 }
374
375 //=================================================================================
376 // function : SelectionIntoArgument()
377 // purpose  : Called when selection has changed or other case
378 //=================================================================================
379 void EntityGUI_SubShapeDlg::SelectionIntoArgument()
380 {
381   if (!isAllSubShapes())
382     return;
383
384   int currentType = GroupPoints->ComboBox1->itemData( GroupPoints->ComboBox1->currentIndex() ).toInt();
385
386   ResetStateOfDialog();
387
388   QString aString = ""; /* name of selection */
389
390   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
391   SALOME_ListIO aSelList;
392   aSelMgr->selectedObjects(aSelList);
393
394   int nbSel = GEOMBase::GetNameOfSelectedIObjects(aSelList, aString, true);
395   if (nbSel == 1) {
396     Handle(SALOME_InteractiveObject) IO = aSelList.First();
397     if (!IO->hasEntry()) {
398       SUIT_Session::session()->activeApplication()->putInfo(tr("GEOM_PRP_SHAPE_IN_STUDY"));
399     }
400     else {
401       TopoDS_Shape S = GEOMBase::GetTopoFromSelection(aSelList);
402       if (S.IsNull() || S.ShapeType() == TopAbs_VERTEX) {
403         myObject = GEOM::GEOM_Object::_nil();
404       }
405       else {
406         myObject = GEOMBase::ConvertIOinGEOMObject(IO);
407         if (!CORBA::is_nil(myObject)) {
408           myShape = S;
409           GroupPoints->LineEdit1->setText(aString);
410           int i = 0;
411           // Solving PAL5590
412           if (myShape.ShapeType() == TopAbs_COMPOUND) {
413             unsigned int nb = NumberOfSubShapes(myShape, TopAbs_COMPOUND);
414             if (nb > 0)
415               i++;
416           }
417           while (i <= myShape.ShapeType()) {
418             GroupPoints->ComboBox1->removeItem(0);
419             i++;
420           }
421           // remove Shape and Flat types for non-compound shapes
422           if (myShape.ShapeType() != TopAbs_COMPOUND) {
423             int idx = GroupPoints->ComboBox1->findData( (int)GEOM::SHAPE );
424             if ( idx != -1 ) GroupPoints->ComboBox1->removeItem( idx );
425             idx = GroupPoints->ComboBox1->findData( (int)GEOM::FLAT );
426             if ( idx != -1 ) GroupPoints->ComboBox1->removeItem( idx );
427           } // if (myShape.ShapeType() != TopAbs_COMPOUND)
428         } // if (!CORBA::is_nil(myObject))
429       } // if (S.IsNull() || S.ShapeType() == TopAbs_VERTEX)
430     } // if (!IO->hasEntry()) ... else
431   } // if (nbSel == 1)
432
433   int idx = GroupPoints->ComboBox1->findData( currentType );
434   if ( idx != -1 )
435     GroupPoints->ComboBox1->setCurrentIndex( idx );
436
437   updateButtonState();
438 }
439
440 //=================================================================================
441 // function : SetEditCurrentArgument()
442 // purpose  :
443 //=================================================================================
444 void EntityGUI_SubShapeDlg::SetEditCurrentArgument()
445 {
446   GroupPoints->LineEdit1->setFocus();
447   myEditCurrentArgument = GroupPoints->LineEdit1;
448
449   GroupPoints->CheckButton1->setChecked(false);
450   SubShapeToggled();
451   SelectionIntoArgument();
452 }
453
454 //=================================================================================
455 // function : LineEditReturnPressed()
456 // purpose  :
457 //=================================================================================
458 void EntityGUI_SubShapeDlg::LineEditReturnPressed()
459 {
460   QLineEdit* send = (QLineEdit*)sender();
461   if (send == GroupPoints->LineEdit1)
462     SetEditCurrentArgument();
463   else
464     return;
465
466   GEOMBase_Skeleton::LineEditReturnPressed();
467 }
468
469 //=================================================================================
470 // function : ResetStateOfDialog()
471 // purpose  : Completely reset the state of method including local context
472 //=================================================================================
473 void EntityGUI_SubShapeDlg::ResetStateOfDialog()
474 {
475   if (myIsHiddenMain) {
476     GEOM_Displayer* aDisplayer = getDisplayer();
477     aDisplayer->Display(myObject);
478     myIsHiddenMain = false;
479   }
480   myObject = GEOM::GEOM_Object::_nil();
481   myShape.Nullify();
482   myEditCurrentArgument->setText("");
483
484   /* type for sub-shape selection */
485   GroupPoints->ComboBox1->clear();
486   for ( int i = 0; i <= (int)GEOM::FLAT; i++ )
487     GroupPoints->ComboBox1->addItem(ShapeTypes[i], i);
488
489   updateButtonState();
490 }
491
492 //=================================================================================
493 // function : SubShapeToggled()
494 // purpose  : Allow user selection of all or only selected sub-shapes
495 //          : Called when 'CheckButton1' state change
496 //=================================================================================
497 void EntityGUI_SubShapeDlg::SubShapeToggled()
498 {
499   GroupPoints->PushButton2->setEnabled(!isAllSubShapes());
500   GroupPoints->PushButton3->setEnabled(!isAllSubShapes());
501   GroupPoints->PushButton4->setEnabled(!isAllSubShapes());
502   myFilterGrp->setEnabled(GroupPoints->CheckButton1->isEnabled() &&
503                           GroupPoints->CheckButton1->isChecked() &&
504                           shapeType() < GEOM::VERTEX);
505
506 #ifndef DISABLE_PLOT2DVIEWER
507   myPlotDistributionButton->setEnabled( myFilterGrp->isEnabled() &&
508                                         ( shapeType() == TopAbs_EDGE || 
509                                           shapeType() == TopAbs_FACE ||
510                                           shapeType() == TopAbs_SOLID ) );
511 #endif
512
513   activateSelection();
514 }
515
516 //=================================================================================
517 // function : ComboTextChanged()
518 // purpose  :
519 //=================================================================================
520 void EntityGUI_SubShapeDlg::ComboTextChanged()
521 {
522   /* Select sub-shapes mode not checked */
523   updateButtonState();
524   SubShapeToggled();
525 }
526
527 //=================================================================================
528 // function : updateButtonState
529 // purpose  :
530 //=================================================================================
531 void EntityGUI_SubShapeDlg::updateButtonState()
532 {
533   bool viewOk = SUIT_Session::session()->activeApplication()->desktop()->activeWindow()->getViewManager()->getType() == OCCViewer_Viewer::Type();
534   bool shapeTypeOk = shapeType() != TopAbs_SHAPE && shapeType() != TopAbs_FLAT && shapeType() != TopAbs_COMPOUND;
535   bool objectOK = !CORBA::is_nil( myObject );
536
537   if ( viewOk && objectOK && shapeTypeOk ) {
538     GroupPoints->CheckButton1->setEnabled( true );
539   }
540   else {
541     GroupPoints->CheckButton1->setChecked( false );
542     GroupPoints->CheckButton1->setEnabled( false );
543   }
544   myFilterGrp->setEnabled(GroupPoints->CheckButton1->isEnabled() && GroupPoints->CheckButton1->isChecked());
545 }
546
547 //=================================================================================
548 // function : isAllSubShapes
549 // purpose  :
550 //=================================================================================
551 bool EntityGUI_SubShapeDlg::isAllSubShapes() const
552 {
553   return !GroupPoints->CheckButton1->isEnabled() || !GroupPoints->CheckButton1->isChecked();
554 }
555
556 //=================================================================================
557 // function : shapeType
558 // purpose  :
559 //=================================================================================
560 int EntityGUI_SubShapeDlg::shapeType() const
561 {
562   return GroupPoints->ComboBox1->itemData(GroupPoints->ComboBox1->currentIndex()).toInt();
563 }
564
565 //=================================================================================
566 // function : showOnlySelected
567 // purpose  :
568 //=================================================================================
569 void EntityGUI_SubShapeDlg::showOnlySelected()
570 {
571   if (CORBA::is_nil(myObject) || isAllSubShapes())
572     return;
573
574   QPushButton* send = (QPushButton*)sender();
575   if (send == GroupPoints->PushButton4) {
576     activateSelection();
577     return;
578   }
579
580   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
581   SALOME_ListIO aSelList;
582   aSelMgr->selectedObjects(aSelList);
583
584   GEOM_Displayer* aDisplayer = getDisplayer();
585
586   if (send == GroupPoints->PushButton3) {
587     aDisplayer->Erase(aSelList, /*forced=*/false, /*updateViewer=*/true);
588   }
589   else {
590     // Mantis issue 0021421: do not hide main shape, if explode on VERTEX
591     SALOME_View* view = GEOM_Displayer::GetActiveView();
592     if (view) {
593       CORBA::String_var aMainEntry = myObject->GetStudyEntry();
594       Handle(SALOME_InteractiveObject) io =
595         new SALOME_InteractiveObject (aMainEntry.in(), "GEOM", "TEMP_IO");
596       if (view->isVisible(io)) myIsHiddenMain = true;
597
598       //keep the selected entry and IO in the map for checking
599       std::map<QString, Handle(SALOME_InteractiveObject)> aSelEntriesMap;
600       SALOME_ListIteratorOfListIO aSelIt(aSelList);
601       for ( ; aSelIt.More(); aSelIt.Next() ) {
602         //fill map <entry, io>
603         Handle(SALOME_InteractiveObject) anSelIO = aSelIt.Value();
604         aSelEntriesMap[anSelIO->getEntry()] = anSelIO;
605       }
606       //get the displayed sub-shapes
607       SALOME_ListIO displayed;
608       view->GetVisible(displayed);
609       // Erase all, except the selected shapes
610       std::map<QString, Handle(SALOME_InteractiveObject)>::iterator 
611         aSelDispIter = aSelEntriesMap.end();
612       SALOME_ListIteratorOfListIO aDispIt( displayed );
613       for ( ; aDispIt.More(); aDispIt.Next() ) {
614         Handle(SALOME_InteractiveObject) anIO = aDispIt.Value();
615         aSelDispIter = aSelEntriesMap.find( anIO->getEntry() );
616         if ( aSelDispIter != aSelEntriesMap.end() ) {
617           //sub-shape is selected, so erase it's record from map to keep in it not displayed, but selected sub-shapes only
618           aSelEntriesMap.erase(aSelDispIter);
619         } else {
620           //sub-shape is not in the map of selected, then erase it from view
621           aDisplayer->Erase( anIO, /*forced = */false, /*updateViewer = */false );
622         }
623       }
624       
625       if ( !aSelEntriesMap.empty() ) {
626         // Build a presentation of the selected, but not displayed sub-shapes
627         TopTools_IndexedMapOfShape aSubShapesMap;
628         TopExp::MapShapes(myShape, aSubShapesMap);
629         QString anEntryBase = aMainEntry.in();
630
631         TopExp_Explorer anExp (myShape, (TopAbs_ShapeEnum)shapeType());
632         for (; anExp.More(); anExp.Next())
633         {
634           TopoDS_Shape aSubShape = anExp.Current();
635           int index = aSubShapesMap.FindIndex(aSubShape);
636           QString anEntry = QString( "TEMP_" ) + anEntryBase + QString("_%1").arg(index);
637           if ( aSelEntriesMap.find( anEntry ) == aSelEntriesMap.end() ) {
638             //skip not selected sub-shapes
639             continue;
640           }
641           SALOME_Prs* aPrs = aDisplayer->buildSubshapePresentation(aSubShape, anEntry, view);
642           if (aPrs) {
643             displayPreview(aPrs, true, false); // append, do not update
644           }
645         }
646       }
647       aDisplayer->UpdateViewer();
648     }
649
650     // Mantis issue 0021421: do not hide main shape, if explode on VERTEX
651     if ((TopAbs_ShapeEnum)shapeType() == TopAbs_VERTEX && myIsHiddenMain) {
652       aDisplayer->Display(myObject);
653     }
654   }
655 }
656
657 //=================================================================================
658 // function : getSelectedSubshapes
659 // purpose  :
660 //=================================================================================
661 int EntityGUI_SubShapeDlg::getSelectedSubshapes (TColStd_IndexedMapOfInteger& theMapIndex)
662 {
663   theMapIndex.Clear();
664
665   SalomeApp_Application* app = myGeomGUI->getApp();
666   if (!app || myObject->_is_nil())
667     return 0;
668
669   LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
670   SALOME_ListIO aSelList;
671   aSelMgr->selectedObjects(aSelList);
672
673   // try to find out and process the global selection
674   // (of not published objects and of published sub-shapes)
675   {
676     SALOME_ListIteratorOfListIO anIter (aSelList);
677     for (int i = 0; anIter.More(); anIter.Next(), i++)
678     {
679       Handle(SALOME_InteractiveObject) anIObj = anIter.Value();
680       QString anEntry = anIObj->getEntry();
681       QString str = "_";
682       int index = anEntry.lastIndexOf(str);
683       if (index > 0) // selection among special preview
684       {
685         anEntry.remove(0, index+1);
686         int anIndex = anEntry.toInt();
687         if (anIndex)
688           theMapIndex.Add(anIndex);
689       }
690       else // selection among published shapes
691       {
692         SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>(app->activeStudy());
693         if (!appStudy) return 0;
694         _PTR(Study) aStudy = appStudy->studyDS();
695
696         _PTR(SObject) aSObj (aStudy->FindObjectID(anEntry.toLatin1().constData()));
697         GEOM::GEOM_Object_var aGeomObj =
698           GEOM::GEOM_Object::_narrow(GeometryGUI::ClientSObjectToObject(aSObj));
699         TopoDS_Shape aShape;
700         if (GEOMBase::GetShape(aGeomObj, aShape)) {
701           if (aGeomObj->GetType() == GEOM_GROUP || aShape.ShapeType() == (TopAbs_ShapeEnum)shapeType()) {
702             TopTools_IndexedMapOfShape aMainMap;
703             TopExp::MapShapes(myShape, aMainMap);
704
705             TopExp_Explorer anExp (aShape, (TopAbs_ShapeEnum)shapeType());
706             for (; anExp.More(); anExp.Next()) {
707               TopoDS_Shape aSubShape = anExp.Current();
708               int anIndex = aMainMap.FindIndex(aSubShape);
709               if (anIndex >= 0) {
710                 theMapIndex.Add(anIndex);
711               }
712             }
713           }
714         }
715       }
716     } // for aSelList
717   }
718
719   return theMapIndex.Extent();
720 }
721
722 //=================================================================================
723 // function : activateSelection
724 // purpose  : Activate selection in accordance with myEditCurrentArgument
725 //=================================================================================
726 void EntityGUI_SubShapeDlg::activateSelection()
727 {
728   bool isApply = ((QPushButton*)sender() == buttonApply());
729   
730   if(!isApply)
731     erasePreview(false);
732
733   // local selection
734   if (!myObject->_is_nil() && !isAllSubShapes())
735   {
736     GEOM_Displayer* aDisplayer = getDisplayer();
737
738     //display mode for main shape
739     if ( myDmMode == -1 ) {
740       SALOME_View* view = GEOM_Displayer::GetActiveView();
741       if (view) {
742         CORBA::String_var aMainEntry = myObject->GetStudyEntry();
743         Handle(SALOME_InteractiveObject) io =
744           new SALOME_InteractiveObject (aMainEntry.in(), "GEOM", "TEMP_IO");
745         if ( view->isVisible( io ) ) {
746           Handle(GEOM_AISShape) aSh = GEOMBase::ConvertIOinGEOMAISShape( io, true );
747           if(!aSh.IsNull())
748             myDmMode = aSh->isTopLevel() ? aSh->prevDisplayMode() : aSh->DisplayMode();
749         }
750         else
751           myDmMode = SUIT_Session::session()->resourceMgr()->integerValue( "Geometry", "display_mode" );
752       }
753     }
754     // Mantis issue 0021421: do not hide main shape, if explode on VERTEX
755     if (shapeType() != TopAbs_VERTEX) {
756       aDisplayer->Erase(myObject, false, false);
757       myIsHiddenMain = true;
758     }
759     else
760       aDisplayer->Display(myObject);
761
762     aDisplayer->SetDisplayMode(myDmMode);
763
764     if(!isApply) {
765       SUIT_ViewWindow* aViewWindow = 0;
766       SUIT_Study* activeStudy = SUIT_Session::session()->activeApplication()->activeStudy();
767       if (activeStudy)
768         aViewWindow = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
769       if (aViewWindow == 0) return;
770
771       SUIT_ViewManager* aViewManager = aViewWindow->getViewManager();
772       if (aViewManager->getType() != OCCViewer_Viewer::Type() &&
773           aViewManager->getType() != SVTK_Viewer::Type())
774         return;
775
776       SUIT_ViewModel* aViewModel = aViewManager->getViewModel();
777       SALOME_View* aView = dynamic_cast<SALOME_View*>(aViewModel);
778       if (aView == 0) return;
779
780       //TopoDS_Shape aMainShape = GEOM_Client::get_client().GetShape(GeometryGUI::GetGeomGen(), myObject);
781
782       TopTools_IndexedMapOfShape aSubShapesMap;
783       TopExp::MapShapes(myShape, aSubShapesMap);
784       CORBA::String_var aMainEntry = myObject->GetStudyEntry();
785       QString anEntryBase = aMainEntry.in();
786
787       TopExp_Explorer anExp (myShape, (TopAbs_ShapeEnum)shapeType());
788       for (; anExp.More(); anExp.Next())
789       {
790         TopoDS_Shape aSubShape = anExp.Current();
791         int index = aSubShapesMap.FindIndex(aSubShape);
792         QString anEntry = QString( "TEMP_" ) + anEntryBase + QString("_%1").arg(index);
793
794         SALOME_Prs* aPrs = aDisplayer->buildSubshapePresentation(aSubShape, anEntry, aView);
795         if (aPrs) {
796           displayPreview(aPrs, true, false); // append, do not update
797         }
798       }
799       aDisplayer->UnsetDisplayMode();
800       aDisplayer->UpdateViewer();
801     }
802   }
803
804   globalSelection(GEOM_ALLSHAPES);
805 }
806
807 //=================================================================================
808 // function : createOperation
809 // purpose  :
810 //=================================================================================
811 GEOM::GEOM_IOperations_ptr EntityGUI_SubShapeDlg::createOperation()
812 {
813   return getGeomEngine()->GetIShapesOperations(getStudyId());
814 }
815
816 //=================================================================================
817 // function : isValid
818 // purpose  :
819 //=================================================================================
820 bool EntityGUI_SubShapeDlg::isValid (QString& msg)
821 {
822   bool isOk = false;
823
824   if (myObject->_is_nil()) {
825     updateButtonState();
826     return isOk;
827   }
828
829   if (isAllSubShapes())
830     isOk = true;
831   else {
832     TColStd_IndexedMapOfInteger aMapIndex;
833     int nbSel = getSelectedSubshapes(aMapIndex);
834     isOk = nbSel > 0;
835
836     if (!isOk)
837       msg += tr("NO_SUBSHAPES_SELECTED");
838   }
839
840   return isOk;
841 }
842
843 //=================================================================================
844 // function : execute
845 // purpose  :
846 //=================================================================================
847 bool EntityGUI_SubShapeDlg::execute (ObjectList& objects)
848 {
849   GEOM::GEOM_IShapesOperations_var anOper = GEOM::GEOM_IShapesOperations::_narrow(getOperation());
850
851   if (!isAllSubShapes()) {
852     // manual selection
853     TColStd_IndexedMapOfInteger aMapIndex;
854     int nbSel = getSelectedSubshapes(aMapIndex);
855
856     if (nbSel > 0) {
857       int i;
858
859       GEOM::ListOfLong_var anArray = new GEOM::ListOfLong;
860       anArray->length(nbSel);
861
862       for (i = 1; i <= nbSel; i++)
863         anArray[i - 1] = aMapIndex.FindKey(i);
864
865       GEOM::ListOfGO_var aList = anOper->MakeSubShapes(myObject, anArray);
866       int n = aList->length();
867       for (i = 0; i < n; i++)
868         objects.push_back(GEOM::GEOM_Object::_duplicate(aList[i]));
869     }
870   }
871   else {
872     GEOM::ListOfGO_var aList = anOper->ExtractSubShapes(myObject, shapeType(), true);
873     if (!aList->length())
874       return false;
875     for (int i = 0, n = aList->length(); i < n; i++)
876       objects.push_back(GEOM::GEOM_Object::_duplicate(aList[i]));
877   }
878
879   return objects.size();
880 }
881
882 //================================================================
883 // Function : getFather
884 // Purpose  : Get father object for object to be added in study
885 //            (called with addInStudy method)
886 //================================================================
887 GEOM::GEOM_Object_ptr EntityGUI_SubShapeDlg::getFather(GEOM::GEOM_Object_ptr)
888 {
889   return myObject;
890 }
891
892 //================================================================
893 // Function : getNewObjectName
894 // Purpose  :
895 //================================================================
896 QString EntityGUI_SubShapeDlg::getNewObjectName (int) const
897 {
898   return QString::null;
899 }
900
901 //=================================================================================
902 // function : ClickOnOkFilter()
903 // purpose  : highlight and select entities which parameters (length, area or volume) are less than the value specified by the user
904 //=================================================================================
905 void EntityGUI_SubShapeDlg::ClickOnOkFilter()
906 {
907   if (CORBA::is_nil(myObject) || isAllSubShapes() || shapeType() >= GEOM::VERTEX)
908     return;
909   
910   TopTools_IndexedMapOfShape aSubShapesMap;
911   TopExp::MapShapes(myShape, aSubShapesMap);
912   SALOME_View* view = GEOM_Displayer::GetActiveView();
913   getDisplayer()->Erase(myObject, false, false);
914   CORBA::String_var aMainEntry = myObject->GetStudyEntry();
915   QString anEntryBase = aMainEntry.in();
916
917   SALOME_ListIO toSelect;
918
919   TopExp_Explorer anExp (myShape, (TopAbs_ShapeEnum)shapeType());
920   for (; anExp.More(); anExp.Next())
921   {
922     TopoDS_Shape aSubShape = anExp.Current();
923     int index = aSubShapesMap.FindIndex(aSubShape);
924     QString anEntry = QString( "TEMP_" ) + anEntryBase + QString("_%1").arg(index);
925     if ( !getDisplayer()->IsDisplayed( anEntry ) )
926       continue;
927
928     double factor = GEOMUtils::ShapeToDouble(aSubShape).second;
929     double v1 = myLessFilterSpin->value();
930     double v2 = myGreaterFilterSpin->value();
931     bool isLess = myLessFilterCombo->itemData(myLessFilterCombo->currentIndex()).toInt() == Filter_LT ? factor < v1 : factor <= v1;
932     bool isGreater = myGreaterFilterCombo->itemData(myGreaterFilterCombo->currentIndex()).toInt() == Filter_GT ? factor > v2 : factor >= v2;
933     if ( ( myLessFilterCheck->isChecked() && myGreaterFilterCheck->isChecked() && isLess && isGreater ) ||
934          ( myLessFilterCheck->isChecked() && !myGreaterFilterCheck->isChecked() && isLess ) ||
935          ( myGreaterFilterCheck->isChecked() && !myLessFilterCheck->isChecked() && isGreater ) ) {
936       Handle(SALOME_InteractiveObject) io = new SALOME_InteractiveObject();
937       io->setEntry( anEntry.toLatin1().constData() );
938       io->setName( myObject->GetName() );
939       toSelect.Append(io);
940     }
941   }
942   if ( toSelect.Extent() > 0 ) {
943     myGeomGUI->getApp()->selectionMgr()->setSelectedObjects(toSelect);
944     SUIT_MessageBox::information( this,
945                                   tr( "INF_INFO" ),
946                                   tr( "GEOM_SOME_SHAPES_SELECTED").arg( toSelect.Extent() ),
947                                   tr( "BUT_OK" ) );
948   }
949   else {
950     SUIT_MessageBox::information( this,
951                                   tr( "INF_INFO" ),
952                                   tr( "GEOM_NO_SHAPES_SELECTED" ),
953                                   tr( "BUT_OK" ) );
954   }
955   updateButtonState();
956 }
957
958 #ifndef DISABLE_PLOT2DVIEWER
959 //=================================================================================
960 // function : ClickOnPlot()
961 // purpose  : opens "Shape Statistics" dialog box in order to plot sub-shapes distribution.
962 //=================================================================================
963 void EntityGUI_SubShapeDlg::ClickOnPlot()
964 {
965   QDialog* dlg = new MeasureGUI_ShapeStatisticsDlg( this, myShape, (TopAbs_ShapeEnum)shapeType() );
966   if ( dlg ) {
967     dlg->show();
968   }
969 }
970 #endif
971
972 //=================================================================================
973 // function : MeasureToggled()
974 // purpose  :
975 //          : Called when 'myLessFilterCheck' or 'myGreaterFilterCheck' state change
976 //=================================================================================
977 void EntityGUI_SubShapeDlg::MeasureToggled()
978 {
979   myLessFilterSpin->setEnabled(myLessFilterCheck->isChecked());
980   myLessFilterCombo->setEnabled(myLessFilterCheck->isChecked());
981   myGreaterFilterSpin->setEnabled(myGreaterFilterCheck->isChecked());
982   myGreaterFilterCombo->setEnabled(myGreaterFilterCheck->isChecked());
983   myApplyFilterButton->setEnabled(myLessFilterCheck->isChecked() || myGreaterFilterCheck->isChecked());
984 }
985
986 //=================================================================================
987 // function : getSourceObjects
988 // purpose  : virtual method to get source objects
989 //=================================================================================
990 QList<GEOM::GeomObjPtr> EntityGUI_SubShapeDlg::getSourceObjects()
991 {
992   QList<GEOM::GeomObjPtr> res;
993   GEOM::GeomObjPtr aGeomObjPtr(myObject);
994   res << aGeomObjPtr;
995   return res;
996 }