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