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