Salome HOME
0021147: EDF GEOM: Difference between compound of line and compound of edges
[modules/geom.git] / src / EntityGUI / EntityGUI_SubShapeDlg.cxx
1 //  Copyright (C) 2007-2010  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.
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 // GEOM GEOMGUI : GUI for Geometry component
23 // File   : EntityGUI_SubShapeDlg.cxx
24 // Author : Lucien PIGNOLONI, Open CASCADE S.A.S.
25
26 #include "EntityGUI_SubShapeDlg.h"
27
28 #include <DlgRef.h>
29 #include <GeometryGUI.h>
30 #include <GEOMBase.h>
31
32 #include <SUIT_Desktop.h>
33 #include <SUIT_ResourceMgr.h>
34 #include <SUIT_Session.h>
35 #include <SUIT_ViewManager.h>
36 #include <SUIT_ViewWindow.h>
37 #include <OCCViewer_ViewModel.h>
38 #include <SalomeApp_Application.h>
39 #include <LightApp_SelectionMgr.h>
40
41 #include <TColStd_IndexedMapOfInteger.hxx>
42 #include <TopoDS_Iterator.hxx>
43 #include <TopExp_Explorer.hxx>
44 #include <TopTools_MapOfShape.hxx>
45
46 #include <QMessageBox>
47
48 //=================================================================================
49 // class    : EntityGUI_SubShapeDlg
50 // purpose  : Constructs a EntityGUI_SubShapeDlg which is a child of 'parent', with the
51 //            name 'name' and widget flags set to 'f'.
52 //            The dialog will by default be modeless, unless you set 'modal' to
53 //            TRUE to construct a modal dialog.
54 //=================================================================================
55 EntityGUI_SubShapeDlg::EntityGUI_SubShapeDlg( GeometryGUI* theGeometryGUI, QWidget* parent,
56                                               bool modal, Qt::WindowFlags fl )
57   : GEOMBase_Skeleton( theGeometryGUI, parent, modal, fl )
58 {
59   QPixmap image0( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_DLG_SUBSHAPE" ) ) );
60   QPixmap image1( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ) );
61
62   setWindowTitle( tr( "GEOM_SUBSHAPE_TITLE" ) );
63
64   /***************************************************************/
65   mainFrame()->GroupConstructors->setTitle( tr( "GEOM_SUB_SHAPE" ) );
66   mainFrame()->RadioButton1->setIcon( image0 );
67   mainFrame()->RadioButton2->setAttribute( Qt::WA_DeleteOnClose );
68   mainFrame()->RadioButton2->close();
69   mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose );
70   mainFrame()->RadioButton3->close();
71
72   GroupPoints = new DlgRef_1Sel1Check1List( centralWidget() );
73
74   GroupPoints->GroupBox1->setTitle( tr( "GEOM_ARGUMENTS" ) );
75   GroupPoints->TextLabel1->setText( tr( "GEOM_MAIN_OBJECT" ) );
76   GroupPoints->TextLabel2->setText( tr( "GEOM_SUBSHAPE_TYPE" ) );
77   GroupPoints->CheckButton1->setText( tr( "GEOM_SUBSHAPE_SELECT" ) );
78   GroupPoints->PushButton1->setIcon( image1 );
79   GroupPoints->LineEdit1->setReadOnly( true );
80
81   QVBoxLayout* layout = new QVBoxLayout( centralWidget() );
82   layout->setMargin( 0 ); layout->setSpacing( 6 );
83   layout->addWidget( GroupPoints );
84   /***************************************************************/
85
86   setHelpFileName( "create_explode_page.html" );
87
88   mainFrame()->GroupBoxName->hide();
89
90   Init();
91 }
92
93
94 //=================================================================================
95 // function : ~EntityGUI_SubShapeDlg()
96 // purpose  : Destroys the object and frees any allocated resources
97 //=================================================================================
98 EntityGUI_SubShapeDlg::~EntityGUI_SubShapeDlg()
99 {
100 }
101
102
103 //=================================================================================
104 // function : Init()
105 // purpose  :
106 //=================================================================================
107 void EntityGUI_SubShapeDlg::Init()
108 {
109   /* init variables */
110   myEditCurrentArgument = GroupPoints->LineEdit1;
111   myObject = GEOM::GEOM_Object::_nil();
112
113   myWithShape = true;
114
115   /* type for sub shape selection */
116   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Compound" );
117   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Compsolid" );
118   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Solid" );
119   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Shell" );
120   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Face" );
121   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Wire" );
122   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Edge" );
123   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Vertex" );
124   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Shape" );
125
126   if ( SUIT_Session::session()->activeApplication()->desktop()->activeWindow()->getViewManager()->getType() 
127        != OCCViewer_Viewer::Type() )
128     GroupPoints->CheckButton1->setEnabled( false );
129
130   /* signals and slots connections */
131   connect( myGeomGUI, SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( DeactivateActiveDialog() ) );
132
133   connect( buttonOk(),    SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
134   connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
135
136   connect( GroupPoints->PushButton1,  SIGNAL( clicked() ),       this, SLOT( SetEditCurrentArgument() ) );
137   connect( GroupPoints->LineEdit1,    SIGNAL( returnPressed() ), this, SLOT( LineEditReturnPressed() ) );
138
139   connect( GroupPoints->ComboBox1,    SIGNAL( activated( int ) ),    this, SLOT( ComboTextChanged() ) );
140   connect( GroupPoints->CheckButton1, SIGNAL( stateChanged( int ) ), this, SLOT( SubShapeToggled() ) );
141
142   connect( myGeomGUI->getApp()->selectionMgr(),
143            SIGNAL( currentSelectionChanged( )), this, SLOT( SelectionIntoArgument() ) );
144
145   updateButtonState();
146   resize(100,100);
147   SelectionIntoArgument();
148 }
149
150
151 //=================================================================================
152 // function : ClickOnOk()
153 // purpose  :
154 //=================================================================================
155 void EntityGUI_SubShapeDlg::ClickOnOk()
156 {
157   if ( ClickOnApply() )
158     ClickOnCancel();
159 }
160
161
162 //=================================================================================
163 // function : ClickOnApply()
164 // purpose  :
165 //=================================================================================
166 bool EntityGUI_SubShapeDlg::ClickOnApply()
167 {
168   SUIT_Session::session()->activeApplication()->putInfo( "" );
169     
170   /* Explode all sub shapes */
171   if ( isAllSubShapes() ) {
172     /* More than 30 subshapes : ask confirmation */
173     unsigned int nb = NumberOfSubShapes( myShape, shapeType() );
174     if ( nb > 30 ) {
175       const QString caption = tr( "GEOM_CONFIRM" );
176       const QString text = tr( "GEOM_CONFIRM_INFO" ).arg( nb );
177       const QString button0 = tr( "GEOM_BUT_EXPLODE" );
178       const QString button1 = tr( "GEOM_BUT_CANCEL" );
179
180       if ( QMessageBox::warning( this, caption, text, button0, button1 ) != 0 )
181         return false;  /* aborted */
182     }
183   }
184
185   bool isOk = onAccept();
186
187   // restore selection, corresponding to current selection mode
188   SubShapeToggled();
189
190   return isOk;
191 }
192
193
194 //=================================================================================
195 // function : SelectionIntoArgument()
196 // purpose  : Called when selection as changed or other case
197 //          : used only by SelectButtonC1A1 (LineEditC1A1)
198 //=================================================================================
199 void EntityGUI_SubShapeDlg::SelectionIntoArgument()
200 {
201   if (!isAllSubShapes())
202     return;
203
204   ResetStateOfDialog();
205
206   QString aString = ""; /* name of selection */
207
208   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
209   SALOME_ListIO aSelList;
210   aSelMgr->selectedObjects(aSelList);
211
212   int nbSel = GEOMBase::GetNameOfSelectedIObjects(aSelList, aString, true);
213   if (nbSel != 1)
214     return;
215
216   Handle(SALOME_InteractiveObject) IO = aSelList.First();
217   if ( !IO->hasEntry() ) {
218     SUIT_Session::session()->activeApplication()->putInfo( tr( "GEOM_PRP_SHAPE_IN_STUDY" ) );
219     updateButtonState();
220     return;
221   }
222
223   TopoDS_Shape S = GEOMBase::GetTopoFromSelection( aSelList );
224   if ( S.IsNull() || S.ShapeType() == TopAbs_VERTEX ) {
225     myObject = GEOM::GEOM_Object::_nil();
226     updateButtonState();
227     return;
228   }
229
230   myObject = GEOMBase::ConvertIOinGEOMObject( IO );
231   if ( myObject->_is_nil() ) {
232     updateButtonState();
233     return;
234   }
235
236   myShape = S;
237   GroupPoints->LineEdit1->setText(aString);
238
239   int SelectedShapeType = GroupPoints->ComboBox1->currentIndex();
240   int count = GroupPoints->ComboBox1->count();
241
242   if (myWithShape)
243     count = count - 1;
244
245   int i = 0;
246   // Solving PAL5590
247   if (myShape.ShapeType() == TopAbs_COMPOUND) {
248     unsigned int nb = NumberOfSubShapes(myShape, TopAbs_COMPOUND);
249     if ( nb > 0 )
250       i++;
251   }
252   while (i <= myShape.ShapeType()) {
253     GroupPoints->ComboBox1->removeItem(0);
254     i++;
255   }
256
257   if (myShape.ShapeType() == TopAbs_COMPOUND) {
258     if (myWithShape == false) {
259       GroupPoints->ComboBox1->insertItem(GroupPoints->ComboBox1->count(), "Shape");
260       myWithShape = true;
261     }
262   }
263   else {
264     if ( myWithShape == true ) {
265       GroupPoints->ComboBox1->removeItem( GroupPoints->ComboBox1->count() - 1 );
266       myWithShape = false;
267     }
268   }
269
270   int count1 = GroupPoints->ComboBox1->count();
271   if ( myWithShape )
272     count1 = count1 - 1;
273
274   if ( SelectedShapeType > myShape.ShapeType() ) {
275     if ( SelectedShapeType == 8 ) {
276       if ( myShape.ShapeType() != TopAbs_COMPOUND ) {
277         GroupPoints->ComboBox1->setCurrentIndex( 0 );
278         ComboTextChanged();
279       }
280     }
281     else
282       GroupPoints->ComboBox1->setCurrentIndex( count1 - count + SelectedShapeType );
283   }
284   else {
285     GroupPoints->ComboBox1->setCurrentIndex( 0 );
286     ComboTextChanged();
287   }
288
289   updateButtonState();
290 }
291
292
293 //=================================================================================
294 // function : SetEditCurrentArgument()
295 // purpose  :
296 //=================================================================================
297 void EntityGUI_SubShapeDlg::SetEditCurrentArgument()
298 {
299   GroupPoints->LineEdit1->setFocus();
300   myEditCurrentArgument = GroupPoints->LineEdit1;
301   
302   GroupPoints->CheckButton1->setChecked( false );
303   SubShapeToggled();
304   SelectionIntoArgument();
305 }
306
307
308 //=================================================================================
309 // function : LineEditReturnPressed()
310 // purpose  :
311 //=================================================================================
312 void EntityGUI_SubShapeDlg::LineEditReturnPressed()
313 {  
314   QLineEdit* send = (QLineEdit*)sender();
315   if ( send == GroupPoints->LineEdit1 )
316     SetEditCurrentArgument();
317   else
318     return;
319
320   GEOMBase_Skeleton::LineEditReturnPressed();
321 }
322
323
324 //=================================================================================
325 // function : DeactivateActiveDialog()
326 // purpose  :
327 //=================================================================================
328 void EntityGUI_SubShapeDlg::DeactivateActiveDialog()
329 {
330   if ( mainFrame()->GroupConstructors->isEnabled() ) {
331     GEOMBase_Skeleton::DeactivateActiveDialog();
332   }
333 }
334
335
336 //=================================================================================
337 // function : ActivateThisDialog()
338 // purpose  :
339 //=================================================================================
340 void EntityGUI_SubShapeDlg::ActivateThisDialog()
341 {
342   GEOMBase_Skeleton::ActivateThisDialog();
343   connect( myGeomGUI->getApp()->selectionMgr(),
344            SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) );
345   SubShapeToggled();
346   updateButtonState();
347 }
348
349
350 //=================================================================================
351 // function : enterEvent()
352 // purpose  :
353 //=================================================================================
354 void EntityGUI_SubShapeDlg::enterEvent( QEvent* )
355 {
356   if ( !mainFrame()->GroupConstructors->isEnabled() )
357     ActivateThisDialog();
358 }
359
360 //=================================================================================
361 // function : ResetStateOfDialog()
362 // purpose  : Completely reset the state of method including local context
363 //=================================================================================
364 void EntityGUI_SubShapeDlg::ResetStateOfDialog()
365 {
366   myObject = GEOM::GEOM_Object::_nil();
367   myShape.Nullify();
368   myEditCurrentArgument->setText( "" );
369
370   int SelectedShapeType = GroupPoints->ComboBox1->currentIndex();
371   int count = GroupPoints->ComboBox1->count();
372   if ( myWithShape )
373     count = count - 1;
374
375   /* type for sub shape selection */
376   GroupPoints->ComboBox1->clear();
377   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Compound" );
378   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Compsolid" );
379   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Solid" );
380   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Shell" );
381   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Face" );
382   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Wire" );
383   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Edge" );
384   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Vertex" );
385   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Shape" );
386   
387   myWithShape = true;
388   
389   GroupPoints->ComboBox1->setCurrentIndex( 8 - count + SelectedShapeType );
390   ComboTextChanged();
391
392   updateButtonState();
393 }
394
395
396 //=================================================================================
397 // function : SubShapeToggled()
398 // purpose  : Allow user selection of all or only selected sub shapes
399 //          : Called when 'CheckButton1' state change
400 //=================================================================================
401 void EntityGUI_SubShapeDlg::SubShapeToggled()
402 {
403   globalSelection( GEOM_ALLSHAPES );
404
405   if ( !isAllSubShapes() )
406     localSelection( myObject, shapeType() );
407 }
408
409
410 //=================================================================================
411 // function : ComboTextChanged()
412 // purpose  : 
413 //=================================================================================
414 void EntityGUI_SubShapeDlg::ComboTextChanged()
415 {
416   /* Select sub shapes mode not checked */
417   updateButtonState();
418   SubShapeToggled();    
419 }
420
421
422 //=================================================================================
423 // function : NumberOfSubShapes()
424 // purpose  :
425 //=================================================================================
426 unsigned int EntityGUI_SubShapeDlg::NumberOfSubShapes( const TopoDS_Shape& S,
427                                                        const int shapeType ) const
428 {
429   if ( S.IsNull() )
430     return 0;
431
432   unsigned int index = 0;
433   TopTools_MapOfShape M;
434
435   if ( S.ShapeType() == TopAbs_COMPOUND &&
436        ( TopAbs_ShapeEnum(shapeType) == TopAbs_SHAPE ||
437          TopAbs_ShapeEnum(shapeType) == TopAbs_COMPSOLID ||
438          TopAbs_ShapeEnum(shapeType) == TopAbs_COMPOUND ) ) {
439     TopoDS_Iterator It( S, Standard_True, Standard_True );
440     for ( ; It.More(); It.Next() ) {
441       if ( M.Add( It.Value() ) ) {
442         if ( TopAbs_ShapeEnum( shapeType ) == TopAbs_SHAPE ||
443              TopAbs_ShapeEnum( shapeType ) == It.Value().ShapeType() ) {
444           index++;
445         }
446       }
447     }
448   } 
449   else {
450     TopExp_Explorer Exp ( S, TopAbs_ShapeEnum( shapeType ) );
451     for ( ; Exp.More(); Exp.Next() ) {
452       if ( M.Add( Exp.Current() ) ) {
453         index++;
454       }
455     }
456   }
457
458   M.Clear();
459   return index;
460 }
461
462 //=================================================================================
463 // function : updateButtonState
464 // purpose  :
465 //=================================================================================
466 void EntityGUI_SubShapeDlg::updateButtonState()
467 {
468   if ( SUIT_Session::session()->activeApplication()->desktop()->activeWindow()->getViewManager()->getType() != OCCViewer_Viewer::Type() ||
469        myObject->_is_nil() || shapeType() == TopAbs_SHAPE || shapeType() == TopAbs_COMPOUND ) {
470     GroupPoints->CheckButton1->setChecked( false );
471     GroupPoints->CheckButton1->setEnabled( false );
472   }
473   else
474     GroupPoints->CheckButton1->setEnabled( true );
475 }
476
477 //=================================================================================
478 // function : isAllSubShapes
479 // purpose  :
480 //=================================================================================
481 bool EntityGUI_SubShapeDlg::isAllSubShapes() const
482 {
483   return !GroupPoints->CheckButton1->isChecked() || !GroupPoints->CheckButton1->isEnabled();
484 }
485
486 //=================================================================================
487 // function : shapeType
488 // purpose  :
489 //=================================================================================
490 int EntityGUI_SubShapeDlg::shapeType() const
491 {
492   int type = GroupPoints->ComboBox1->currentIndex();
493
494   if ( myObject->_is_nil() )
495     return type;
496
497   // Solving PAL5590
498   type += myShape.ShapeType() + 1;
499   if ( myShape.ShapeType() == TopAbs_COMPOUND &&
500        NumberOfSubShapes( myShape, TopAbs_COMPOUND ) > 0 ) {
501     type--;
502   }
503
504   return type;
505 }
506
507 //=================================================================================
508 // function : createOperation
509 // purpose  :
510 //=================================================================================
511 GEOM::GEOM_IOperations_ptr EntityGUI_SubShapeDlg::createOperation()
512 {
513   return getGeomEngine()->GetIShapesOperations( getStudyId() );
514 }
515
516 //=================================================================================
517 // function : isValid
518 // purpose  :
519 //=================================================================================
520 bool EntityGUI_SubShapeDlg::isValid (QString& msg)
521 {
522   bool isOk = false;
523
524   if (myObject->_is_nil()) {
525     updateButtonState();
526     return isOk;
527   }
528
529   if (isAllSubShapes())
530     isOk = true;
531   else {
532     LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
533     SALOME_ListIO aSelList;
534     aSelMgr->selectedObjects(aSelList);
535
536     if (aSelList.Extent() == 1) {
537       GEOM::GEOM_Object_var anObj = GEOMBase::ConvertIOinGEOMObject( aSelList.First() );
538       if ( !anObj->_is_nil() ) {
539         TColStd_IndexedMapOfInteger aMapIndex;
540         aSelMgr->GetIndexes(aSelList.First(), aMapIndex);
541         isOk = aMapIndex.Extent() > 0;
542         if (!isOk)
543           msg += tr("NO_SUBSHAPES_SELECTED");
544       }
545     }
546   }
547
548   return isOk;
549 }
550
551 //=================================================================================
552 // function : execute
553 // purpose  :
554 //=================================================================================
555 bool EntityGUI_SubShapeDlg::execute (ObjectList& objects)
556 {
557   GEOM::GEOM_IShapesOperations_var anOper = GEOM::GEOM_IShapesOperations::_narrow(getOperation());
558   GEOM::ListOfGO_var aList = anOper->MakeAllSubShapes(myObject, shapeType(), true);
559
560   if (!aList->length())
561     return false;
562
563   // Throw away sub-shapes not selected by user if not in preview mode 
564   // and manual selection is active
565   if (!isAllSubShapes()) {
566     LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
567     SALOME_ListIO aSelList;
568     aSelMgr->selectedObjects(aSelList);
569
570     if (aSelList.Extent() == 1) {
571       GEOM::GEOM_Object_var anObj =
572         GEOMBase::ConvertIOinGEOMObject( aSelList.First() );
573
574       if ( !anObj->_is_nil() ) {
575         TColStd_IndexedMapOfInteger aMapIndex;
576         aSelMgr->GetIndexes(aSelList.First(), aMapIndex);
577
578         GEOM::GEOM_ILocalOperations_var aLocOp = 
579           getGeomEngine()->GetILocalOperations(getStudyId());
580
581         for (int i = 0, n = aList->length(); i < n; i++)
582           if (aMapIndex.Contains(aLocOp->GetSubShapeIndex(myObject, aList[i])))
583             objects.push_back(GEOM::GEOM_Object::_duplicate(aList[i]));
584       }
585     }
586   }
587   else
588     for (int i = 0, n = aList->length(); i < n; i++)
589       objects.push_back(GEOM::GEOM_Object::_duplicate(aList[i]));
590   
591   return objects.size();
592 }
593
594 //================================================================
595 // Function : getFather
596 // Purpose  : Get father object for object to be added in study
597 //            ( called with addInStudy method )
598 //================================================================
599 GEOM::GEOM_Object_ptr EntityGUI_SubShapeDlg::getFather( GEOM::GEOM_Object_ptr )
600 {
601   return myObject;
602 }
603
604 QString EntityGUI_SubShapeDlg::getNewObjectName() const
605 {
606   return QString::null;
607 }