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