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