Salome HOME
7d1a465b5864eefd9e93706603d85b9344959ea8
[modules/geom.git] / 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   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
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   int nbSel = GEOMBase::GetNameOfSelectedIObjects( selectedIO(), aString, true );
209   if ( nbSel != 1 )
210     return;
211
212   TopoDS_Shape S;
213   Handle(SALOME_InteractiveObject) IO = firstIObject();
214   if ( !IO->hasEntry() ) {
215     SUIT_Session::session()->activeApplication()->putInfo( tr( "GEOM_PRP_SHAPE_IN_STUDY" ) );
216     updateButtonState();
217     return;
218   }
219
220   if ( !GEOMBase::GetTopoFromSelection( selectedIO(), S ) ||
221        S.IsNull() ||
222        S.ShapeType() == TopAbs_VERTEX ) {
223     myObject = GEOM::GEOM_Object::_nil();
224     updateButtonState();
225     return;
226   }
227
228
229   Standard_Boolean testResult;
230   myObject = GEOMBase::ConvertIOinGEOMObject( IO, testResult );
231   if ( !testResult || myObject->_is_nil() ) {
232     updateButtonState();
233     return;
234   }
235
236   myShape = S;
237   GroupPoints->LineEdit1->setText( aString );
238
239
240   int SelectedShapeType = GroupPoints->ComboBox1->currentIndex();
241   int count = GroupPoints->ComboBox1->count();
242
243   if ( myWithShape )
244     count = count - 1;
245
246   int i = 0;
247   // Solving PAL5590
248   if ( myShape.ShapeType() == TopAbs_COMPOUND ) {
249     unsigned int nb = NumberOfSubShapes(myShape, TopAbs_COMPOUND);
250     if ( nb > 0 )
251       i++;
252   }
253   while ( i <= myShape.ShapeType() ) {
254     GroupPoints->ComboBox1->removeItem( 0 );
255     i++;
256   }
257
258   if ( myShape.ShapeType() == TopAbs_COMPOUND ) {
259     if ( myWithShape == false ) {
260       GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Shape" );
261       myWithShape = true;
262     }
263   }
264   else {
265     if ( myWithShape == true ) {
266       GroupPoints->ComboBox1->removeItem( GroupPoints->ComboBox1->count() - 1 );
267       myWithShape = false;
268     }
269   }
270
271   int count1 = GroupPoints->ComboBox1->count();
272   if ( myWithShape )
273     count1 = count1 - 1;
274
275   if ( SelectedShapeType > myShape.ShapeType() ) {
276     if ( SelectedShapeType == 8 ) {
277       if ( myShape.ShapeType() != TopAbs_COMPOUND ) {
278         GroupPoints->ComboBox1->setCurrentIndex( 0 );
279         ComboTextChanged();
280       }
281     }
282     else
283       GroupPoints->ComboBox1->setCurrentIndex( count1 - count + SelectedShapeType );
284   }
285   else {
286     GroupPoints->ComboBox1->setCurrentIndex( 0 );
287     ComboTextChanged();
288   }
289
290   updateButtonState();
291 }
292
293
294 //=================================================================================
295 // function : SetEditCurrentArgument()
296 // purpose  :
297 //=================================================================================
298 void EntityGUI_SubShapeDlg::SetEditCurrentArgument()
299 {
300   GroupPoints->LineEdit1->setFocus();
301   myEditCurrentArgument = GroupPoints->LineEdit1;
302   
303   GroupPoints->CheckButton1->setChecked( false );
304   SubShapeToggled();
305   SelectionIntoArgument();
306 }
307
308
309 //=================================================================================
310 // function : LineEditReturnPressed()
311 // purpose  :
312 //=================================================================================
313 void EntityGUI_SubShapeDlg::LineEditReturnPressed()
314 {  
315   QLineEdit* send = (QLineEdit*)sender();
316   if ( send == GroupPoints->LineEdit1 )
317     SetEditCurrentArgument();
318   else
319     return;
320
321   GEOMBase_Skeleton::LineEditReturnPressed();
322 }
323
324
325 //=================================================================================
326 // function : DeactivateActiveDialog()
327 // purpose  :
328 //=================================================================================
329 void EntityGUI_SubShapeDlg::DeactivateActiveDialog()
330 {
331   if ( mainFrame()->GroupConstructors->isEnabled() ) {
332     GEOMBase_Skeleton::DeactivateActiveDialog();
333   }
334 }
335
336
337 //=================================================================================
338 // function : ActivateThisDialog()
339 // purpose  :
340 //=================================================================================
341 void EntityGUI_SubShapeDlg::ActivateThisDialog()
342 {
343   GEOMBase_Skeleton::ActivateThisDialog();
344   connect( myGeomGUI->getApp()->selectionMgr(),
345            SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) );
346   SubShapeToggled();
347   updateButtonState();
348 }
349
350
351 //=================================================================================
352 // function : enterEvent()
353 // purpose  :
354 //=================================================================================
355 void EntityGUI_SubShapeDlg::enterEvent( QEvent* )
356 {
357   if ( !mainFrame()->GroupConstructors->isEnabled() )
358     ActivateThisDialog();
359 }
360
361 //=================================================================================
362 // function : ResetStateOfDialog()
363 // purpose  : Completely reset the state of method including local context
364 //=================================================================================
365 void EntityGUI_SubShapeDlg::ResetStateOfDialog()
366 {
367   myObject = GEOM::GEOM_Object::_nil();
368   myShape.Nullify();
369   myEditCurrentArgument->setText( "" );
370
371   int SelectedShapeType = GroupPoints->ComboBox1->currentIndex();
372   int count = GroupPoints->ComboBox1->count();
373   if ( myWithShape )
374     count = count - 1;
375
376   /* type for sub shape selection */
377   GroupPoints->ComboBox1->clear();
378   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Compound" );
379   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Compsolid" );
380   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Solid" );
381   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Shell" );
382   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Face" );
383   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Wire" );
384   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Edge" );
385   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Vertex" );
386   GroupPoints->ComboBox1->insertItem( GroupPoints->ComboBox1->count(), "Shape" );
387   
388   myWithShape = true;
389   
390   GroupPoints->ComboBox1->setCurrentIndex( 8 - count + SelectedShapeType );
391   ComboTextChanged();
392
393   updateButtonState();
394 }
395
396
397 //=================================================================================
398 // function : SubShapeToggled()
399 // purpose  : Allow user selection of all or only selected sub shapes
400 //          : Called when 'CheckButton1' state change
401 //=================================================================================
402 void EntityGUI_SubShapeDlg::SubShapeToggled()
403 {
404   globalSelection( GEOM_ALLSHAPES );
405
406   if ( !isAllSubShapes() )
407     localSelection( myObject, shapeType() );
408 }
409
410
411 //=================================================================================
412 // function : ComboTextChanged()
413 // purpose  : 
414 //=================================================================================
415 void EntityGUI_SubShapeDlg::ComboTextChanged()
416 {
417   /* Select sub shapes mode not checked */
418   updateButtonState();
419   SubShapeToggled();    
420 }
421
422
423 //=================================================================================
424 // function : NumberOfSubShapes()
425 // purpose  :
426 //=================================================================================
427 unsigned int EntityGUI_SubShapeDlg::NumberOfSubShapes( const TopoDS_Shape& S,
428                                                        const int shapeType ) const
429 {
430   if ( S.IsNull() )
431     return 0;
432
433   unsigned int index = 0;
434   TopTools_MapOfShape M;
435
436   if ( S.ShapeType() == TopAbs_COMPOUND &&
437        ( TopAbs_ShapeEnum(shapeType) == TopAbs_SHAPE ||
438          TopAbs_ShapeEnum(shapeType) == TopAbs_COMPSOLID ||
439          TopAbs_ShapeEnum(shapeType) == TopAbs_COMPOUND ) ) {
440     TopoDS_Iterator It( S, Standard_True, Standard_True );
441     for ( ; It.More(); It.Next() ) {
442       if ( M.Add( It.Value() ) ) {
443         if ( TopAbs_ShapeEnum( shapeType ) == TopAbs_SHAPE ||
444              TopAbs_ShapeEnum( shapeType ) == It.Value().ShapeType() ) {
445           index++;
446         }
447       }
448     }
449   } 
450   else {
451     TopExp_Explorer Exp ( S, TopAbs_ShapeEnum( shapeType ) );
452     for ( ; Exp.More(); Exp.Next() ) {
453       if ( M.Add( Exp.Current() ) ) {
454         index++;
455       }
456     }
457   }
458
459   M.Clear();
460   return index;
461 }
462
463 //=================================================================================
464 // function : updateButtonState
465 // purpose  :
466 //=================================================================================
467 void EntityGUI_SubShapeDlg::updateButtonState()
468 {
469   if ( SUIT_Session::session()->activeApplication()->desktop()->activeWindow()->getViewManager()->getType() != OCCViewer_Viewer::Type() ||
470        myObject->_is_nil() || shapeType() == TopAbs_SHAPE || shapeType() == TopAbs_COMPOUND ) {
471     GroupPoints->CheckButton1->setChecked( false );
472     GroupPoints->CheckButton1->setEnabled( false );
473   }
474   else
475     GroupPoints->CheckButton1->setEnabled( true );
476 }
477
478 //=================================================================================
479 // function : isAllSubShapes
480 // purpose  :
481 //=================================================================================
482 bool EntityGUI_SubShapeDlg::isAllSubShapes() const
483 {
484   return !GroupPoints->CheckButton1->isChecked() || !GroupPoints->CheckButton1->isEnabled();
485 }
486
487 //=================================================================================
488 // function : shapeType
489 // purpose  :
490 //=================================================================================
491 int EntityGUI_SubShapeDlg::shapeType() const
492 {
493   int type = GroupPoints->ComboBox1->currentIndex();
494
495   if ( myObject->_is_nil() )
496     return type;
497
498   // Solving PAL5590
499   type += myShape.ShapeType() + 1;
500   if ( myShape.ShapeType() == TopAbs_COMPOUND &&
501        NumberOfSubShapes( myShape, TopAbs_COMPOUND ) > 0 ) {
502     type--;
503   }
504
505   return type;
506 }
507
508 //=================================================================================
509 // function : createOperation
510 // purpose  :
511 //=================================================================================
512 GEOM::GEOM_IOperations_ptr EntityGUI_SubShapeDlg::createOperation()
513 {
514   return getGeomEngine()->GetIShapesOperations( getStudyId() );
515 }
516
517 //=================================================================================
518 // function : isValid
519 // purpose  :
520 //=================================================================================
521 bool EntityGUI_SubShapeDlg::isValid( QString& msg )
522 {
523   bool isOk = false;
524   Standard_Boolean testResult;  
525   GEOM::GEOM_Object_var anObj = GEOMBase::ConvertIOinGEOMObject( firstIObject(), testResult );
526   if ( !testResult || myObject->_is_nil() )  {
527     updateButtonState();
528     return isOk;
529   }
530   if ( !myObject->_is_nil() ) {
531     if ( isAllSubShapes() )
532       isOk = true;
533     else if ( IObjectCount() == 1 ) {
534      if ( testResult && !anObj->_is_nil() ) {
535         TColStd_IndexedMapOfInteger aMapIndex;
536         myGeomGUI->getApp()->selectionMgr()->GetIndexes( firstIObject(), aMapIndex );
537         isOk = aMapIndex.Extent() > 0;
538         if ( !isOk )
539           msg += tr( "NO_SUBSHAPES_SELECTED" );
540       }
541     }
542   }
543   return isOk;
544 }
545
546 //=================================================================================
547 // function : execute
548 // purpose  :
549 //=================================================================================
550 bool EntityGUI_SubShapeDlg::execute( ObjectList& objects )
551 {
552   GEOM::ListOfGO_var aList = GEOM::GEOM_IShapesOperations::_narrow(
553     getOperation() )->MakeExplode( myObject, shapeType(), true );
554     
555   if ( !aList->length() )
556     return false;
557   
558   // Throw away sub-shapes not selected by user if not in preview mode 
559   // and manual selection is active
560   if ( !isAllSubShapes() ) {
561     if ( IObjectCount() == 1 ) {
562       Standard_Boolean aResult = Standard_False;
563       GEOM::GEOM_Object_var anObj =
564         GEOMBase::ConvertIOinGEOMObject( firstIObject(), aResult );
565
566       if ( aResult && !anObj->_is_nil() ) {
567         TColStd_IndexedMapOfInteger aMapIndex;
568         myGeomGUI->getApp()->selectionMgr()->GetIndexes( firstIObject(), aMapIndex );
569
570         GEOM::GEOM_ILocalOperations_var aLocOp = 
571           getGeomEngine()->GetILocalOperations( getStudyId() );
572
573         for ( int i = 0, n = aList->length(); i < n; i++ )
574           if ( aMapIndex.Contains( aLocOp->GetSubShapeIndex( myObject, aList[i] ) ) )
575             objects.push_back( GEOM::GEOM_Object::_duplicate( aList[i] ) );
576       }
577     }
578   }
579   else
580     for ( int i = 0, n = aList->length(); i < n; i++ )
581       objects.push_back( GEOM::GEOM_Object::_duplicate( aList[i] ) );
582   
583   return objects.size();
584 }
585
586 //================================================================
587 // Function : getFather
588 // Purpose  : Get father object for object to be added in study
589 //            ( called with addInStudy method )
590 //================================================================
591 GEOM::GEOM_Object_ptr EntityGUI_SubShapeDlg::getFather( GEOM::GEOM_Object_ptr )
592 {
593   return myObject;
594 }
595
596 QString EntityGUI_SubShapeDlg::getNewObjectName() const
597 {
598   return QString::null;
599 }