]> SALOME platform Git repositories - modules/geom.git/blob - src/GroupGUI/GroupGUI_GroupDlg.cxx
Salome HOME
0020044: EDF 866 GEOM: Extrusion along a path : impossible to select a Wire
[modules/geom.git] / src / GroupGUI / GroupGUI_GroupDlg.cxx
1 // GEOM GEOMGUI : GUI for Geometry component
2 //
3 // Copyright (C) 2004  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   : GroupGUI_GroupDlg.cxx
23 // Author : Sergey ANIKIN, Open CASCADE S.A.S. (sergey.anikin@opencascade.com)
24 //
25
26 #include "GroupGUI_GroupDlg.h"
27
28 #include <LightApp_SelectionMgr.h>
29 #include <SUIT_ResourceMgr.h>
30 #include <SUIT_Desktop.h>
31 #include <SUIT_OverrideCursor.h>
32 #include <SUIT_Session.h>
33 #include <SalomeApp_Application.h>
34 #include <SalomeApp_Study.h>
35
36 #include <DlgRef.h>
37 #include <GEOMBase.h>
38 #include <GeometryGUI.h>
39 #include <GEOMImpl_Types.hxx>
40 #include <GEOM_Displayer.h>
41
42 #include <QLabel>
43 #include <QListWidget>
44 #include <QLineEdit>
45 #include <QMap>
46
47 #include <TColStd_IndexedMapOfInteger.hxx>
48 #include <TColStd_MapOfInteger.hxx>
49 #include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
50
51 enum { ALL_SUBSHAPES = 0, GET_IN_PLACE, SUBSHAPES_OF_SHAPE2 };
52
53 GroupGUI_GroupDlg::GroupGUI_GroupDlg( Mode mode, GeometryGUI* theGeometryGUI, QWidget* parent )
54   : GEOMBase_Skeleton( theGeometryGUI, parent, false ),
55     myMode( mode ),
56     myBusy( false )
57 {
58   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
59
60   QPixmap image0     ( resMgr->loadPixmap( "GEOM", tr( "ICON_OBJBROWSER_VERTEX" ) ) );
61   QPixmap image1     ( resMgr->loadPixmap( "GEOM", tr( "ICON_OBJBROWSER_EDGE" ) ) );
62   QPixmap image2     ( resMgr->loadPixmap( "GEOM", tr( "ICON_OBJBROWSER_FACE" ) ) );
63   QPixmap image3     ( resMgr->loadPixmap( "GEOM", tr( "ICON_OBJBROWSER_SOLID" ) ) );
64   QPixmap iconSelect ( resMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ) );
65
66   setWindowTitle( myMode == CreateGroup ? tr( "CREATE_GROUP_TITLE" ) : tr( "EDIT_GROUP_TITLE" ) );
67
68   // Shape type button group
69   mainFrame()->GroupConstructors->setEnabled( myMode == CreateGroup );
70   mainFrame()->GroupConstructors->setTitle( tr( "SHAPE_TYPE" ) );
71   mainFrame()->RadioButton1->setIcon( image0 );
72   mainFrame()->RadioButton2->setIcon( image1 );
73   mainFrame()->RadioButton3->setIcon( image2 );
74   mainFrame()->RadioButton4->setIcon( image3 );
75   mainFrame()->RadioButton4->show();
76
77   // Group name
78   mainFrame()->GroupBoxName->setTitle( tr( "GROUP_NAME" ) );
79
80   // Main shape and sub-shapes
81   QGroupBox* GroupMedium = new QGroupBox( tr( "MAIN_SUB_SHAPES" ), centralWidget() );
82   QGridLayout* aMedLayout = new QGridLayout( GroupMedium );
83   aMedLayout->setMargin( 9 );
84   aMedLayout->setSpacing( 6 );
85   
86   QLabel* aMainLabel = new QLabel( tr( "MAIN_SHAPE" ), GroupMedium );
87
88   mySelBtn = new QPushButton( GroupMedium );
89   mySelBtn->setIcon( iconSelect );
90   mySelBtn->setEnabled( myMode == CreateGroup );
91
92   myMainName = new QLineEdit( GroupMedium );
93   myMainName->setReadOnly( true );
94   myMainName->setEnabled( myMode == CreateGroup );
95
96   QLabel* aSecondLabel = new QLabel( tr( "SECOND_SHAPE" ), GroupMedium );
97
98   mySelBtn2 = new QPushButton( GroupMedium );
99   mySelBtn2->setIcon( iconSelect );
100   mySelBtn2->setEnabled( false );
101
102   myShape2Name = new QLineEdit( GroupMedium );
103   myShape2Name->setReadOnly( true );
104   myShape2Name->setEnabled( false );
105
106   mySelectionWayGroupBox = new QGroupBox( tr("SHAPE_SEL_RESTR"), GroupMedium );
107   mySelectionWayGroup = new QButtonGroup( mySelectionWayGroupBox );
108   QRadioButton* allSubs     = new QRadioButton( tr( "NO_RESTR" )            , mySelectionWayGroupBox );
109   QRadioButton* inPlaceSubs = new QRadioButton( tr( "GEOM_PARTS_OF_SHAPE2" ), mySelectionWayGroupBox );
110   QRadioButton* shape2Subs  = new QRadioButton( tr( "SUBSHAPES_OF_SHAPE2" ) , mySelectionWayGroupBox );
111   QVBoxLayout* mySelWayLayout = new QVBoxLayout( mySelectionWayGroupBox );
112   mySelWayLayout->setMargin( 9 );
113   mySelWayLayout->setSpacing( 6 );
114   mySelWayLayout->addWidget( allSubs );
115   mySelWayLayout->addWidget( inPlaceSubs );
116   mySelWayLayout->addWidget( shape2Subs );
117   mySelectionWayGroup->addButton( allSubs,     ALL_SUBSHAPES );
118   mySelectionWayGroup->addButton( inPlaceSubs, GET_IN_PLACE );
119   mySelectionWayGroup->addButton( shape2Subs,  SUBSHAPES_OF_SHAPE2 );
120   allSubs->setChecked( true );
121
122   mySelAllBtn = new QPushButton( tr( "SELECT_ALL" ), GroupMedium );
123   myAddBtn    = new QPushButton( tr( "ADD" ), GroupMedium );
124   myRemBtn    = new QPushButton( tr( "REMOVE" ), GroupMedium );
125   myIdList    = new QListWidget( GroupMedium );
126
127   myIdList->setSelectionMode( QAbstractItemView::ExtendedSelection );
128   myIdList->setFlow( QListView::TopToBottom );
129   myIdList->setWrapping( true );
130
131   aMedLayout->addWidget( aMainLabel,             0, 0 );
132   aMedLayout->addWidget( mySelBtn,               0, 1 );
133   aMedLayout->addWidget( myMainName,             0, 2, 1, 2 );
134   aMedLayout->addWidget( aSecondLabel,           1, 0 );
135   aMedLayout->addWidget( mySelBtn2,              1, 1 );
136   aMedLayout->addWidget( myShape2Name,           1, 2, 1, 2 );
137   aMedLayout->addWidget( mySelectionWayGroupBox, 2, 0, 3, 3 );
138   aMedLayout->addWidget( mySelAllBtn,            2, 3 );
139   aMedLayout->addWidget( myAddBtn,               3, 3 );
140   aMedLayout->addWidget( myRemBtn,               4, 3 );
141   aMedLayout->addWidget( myIdList,               5, 0, 1, 4 );
142   aMedLayout->setRowStretch( 5, 1 );
143
144   QVBoxLayout* layout = new QVBoxLayout( centralWidget() );
145   layout->setMargin( 0 ); layout->setSpacing( 6 );
146   layout->addWidget( GroupMedium );
147
148   setHelpFileName( "work_with_groups_page.html" );
149
150   Init();
151 }
152
153 GroupGUI_GroupDlg::~GroupGUI_GroupDlg()
154 {
155 }
156
157 //=================================================================================
158 // function : Init()
159 // purpose  :
160 //=================================================================================
161 void GroupGUI_GroupDlg::Init()
162 {
163   // san -- TODO: clear selected sub-shapes...
164   //mySelSubBtn->setChecked( true );
165   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
166
167   if ( myMode == CreateGroup ) {
168     initName( tr( "GROUP_PREFIX" ) );
169
170     // Get ready for main shape selection
171     myEditCurrentArgument = myMainName;
172
173     connect( this, SIGNAL( constructorsClicked( int ) ),  this, SLOT( ConstructorsClicked( int ) ) );
174     connect( mySelBtn,          SIGNAL( clicked() ),      this, SLOT( SetEditCurrentArgument() ) );
175     connect( mySelBtn2,         SIGNAL( clicked() ),      this, SLOT( SetEditCurrentArgument() ) );
176   }
177   else if (myMode == EditGroup) {
178     SALOME_ListIO aSelList;
179     aSelMgr->selectedObjects(aSelList);
180
181     if (aSelList.Extent()) {
182       Standard_Boolean aResult = Standard_False;
183       GEOM::GEOM_Object_var anObj =
184         GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult);
185
186       if ( aResult && !CORBA::is_nil( anObj ) && anObj->GetType() == GEOM_GROUP ) {
187         myGroup = anObj;
188
189         mainFrame()->ResultName->setText( GEOMBase::GetName( myGroup ) );
190
191         GEOM::GEOM_IGroupOperations_var anOp = GEOM::GEOM_IGroupOperations::_narrow( getOperation() );
192         myMainObj = anOp->GetMainShape( myGroup );
193         if ( !CORBA::is_nil( myMainObj ) )
194           myMainName->setText( GEOMBase::GetName( myMainObj ) );
195
196         setShapeType( (TopAbs_ShapeEnum)anOp->GetType( myGroup ) );
197
198         GEOM::ListOfLong_var aCurrList = anOp->GetObjects( myGroup );
199         for ( int i = 0, n = aCurrList->length(); i < n; i++ )
200           myIdList->addItem( new QListWidgetItem( QString( "%1" ).arg( aCurrList[i] ) ) );
201
202         myEditCurrentArgument = 0;
203       }
204       connect( mySelBtn2, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) );
205     }
206   }
207
208   connect( aSelMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()) );
209
210   connect( buttonOk(),    SIGNAL( clicked() ), this, SLOT( ClickOnOk()    ) );
211   connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
212
213   connect( mySelectionWayGroup, SIGNAL( buttonClicked( int ) ), this, SLOT( SetEditCurrentArgument() ) );
214   connect( mySelAllBtn,         SIGNAL( clicked() ),            this, SLOT( SetEditCurrentArgument() ) );
215   connect( myAddBtn,            SIGNAL( clicked() ),            this, SLOT( add() ) );
216   connect( myRemBtn,            SIGNAL( clicked() ),            this, SLOT( remove() ) );
217   connect( myIdList,            SIGNAL( selectionChanged() ),   this, SLOT( selectionChanged() ) );
218
219   setInPlaceObj(GEOM::GEOM_Object::_nil());
220
221   myBusy = true; // just activate but do not select in the list
222   activateSelection();
223   myBusy = false;
224 }
225
226 //=================================================================================
227 // function : enterEvent()
228 // purpose  :
229 //=================================================================================
230 void GroupGUI_GroupDlg::enterEvent( QEvent* e )
231 {
232   if ( !buttonCancel()->isEnabled() )
233     ActivateThisDialog();
234 }
235
236 //=======================================================================
237 //function : closeEvent
238 //purpose  : remove temporary geom object
239 //=======================================================================
240
241 void GroupGUI_GroupDlg::closeEvent( QCloseEvent* e )
242 {
243   setInPlaceObj( GEOM::GEOM_Object::_nil() );
244
245   GEOMBase_Skeleton::closeEvent( e );
246 }
247
248 //=================================================================================
249 // function : ClickOnOk()
250 // purpose  :
251 //=================================================================================
252 void GroupGUI_GroupDlg::ClickOnOk()
253 {
254   if ( ClickOnApply() )
255     ClickOnCancel();
256 }
257
258 //=================================================================================
259 // function : ClickOnApply()
260 // purpose  :
261 //=================================================================================
262 bool GroupGUI_GroupDlg::ClickOnApply()
263 {
264   if ( !onAccept( myMode == CreateGroup, true ) )
265     return false;
266
267   if ( myMode == CreateGroup )
268     {
269       initName();
270       myIdList->clear();
271     }
272   else
273     activateSelection();
274   return true;
275 }
276
277 //=================================================================================
278 // function : ActivateThisDialog()
279 // purpose  :
280 //=================================================================================
281 void GroupGUI_GroupDlg::ActivateThisDialog()
282 {
283   GEOMBase_Skeleton::ActivateThisDialog();
284
285   connect( ((SalomeApp_Application*)(SUIT_Session::session()->activeApplication()))->selectionMgr(),
286            SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) );
287
288   activateSelection();
289 }
290
291 //=================================================================================
292 // function : LineEditReturnPressed()
293 // purpose  :
294 //=================================================================================
295 void GroupGUI_GroupDlg::LineEditReturnPressed()
296 {
297   QLineEdit* send = ( QLineEdit* )sender();
298
299   if ( send == myMainName && !myEditCurrentArgument ) {
300     myEditCurrentArgument = myMainName;
301     activateSelection();
302   }
303   else
304     GEOMBase_Skeleton::LineEditReturnPressed();
305
306   updateState();
307 }
308
309 //=================================================================================
310 // function : SetEditCurrentArgument()
311 // purpose  :
312 //=================================================================================
313 void GroupGUI_GroupDlg::SetEditCurrentArgument()
314 {
315   QPushButton* send = (QPushButton*)sender();
316
317   if ( send == mySelBtn ) {
318     myEditCurrentArgument = myMainName;
319     myShape2Name->setText( "" );
320   }
321   else if ( /*(QRadioButton*)sender() == mySelSubBtn ||*/ send == mySelAllBtn )
322     myEditCurrentArgument = 0;
323   else if ( send == mySelBtn2 || sender() == mySelectionWayGroup ) {
324     setInPlaceObj( GEOM::GEOM_Object::_nil() );
325     //if ( myPlaceCheckBox->isChecked() )
326     myShape2Name->setText( "" );
327     if ( subSelectionWay() != ALL_SUBSHAPES )
328     {
329       myEditCurrentArgument = myShape2Name;
330     }
331     else {
332       //myEditCurrentArgument = myMainName;
333       myEditCurrentArgument = 0;
334     }
335   }
336
337   activateSelection();
338
339   if ( send == mySelAllBtn ) {
340 //     myShape2Name->setText( "" );
341 //     myPlaceCheckBox->setChecked( false );
342 //     mySelBtn2->setEnabled( false );
343 //     myShape2Name->setEnabled( false );
344     selectAllSubShapes();
345   }
346   else
347     updateState();
348 }
349
350 //=================================================================================
351 // function : onGetInPlace()
352 // purpose  :
353 //=================================================================================
354 void GroupGUI_GroupDlg::onGetInPlace()
355 {
356   setInPlaceObj( GEOM::GEOM_Object::_nil() );
357   myEditCurrentArgument->setText( "" );
358
359   bool isBlocked = myIdList->signalsBlocked();
360   myIdList->blockSignals( true );
361   myIdList->clearSelection();
362   myIdList->blockSignals( isBlocked );
363
364   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
365   SALOME_ListIO aSelList;
366   aSelMgr->selectedObjects(aSelList);
367
368   if (aSelList.Extent() != 1)
369     return;
370
371   Standard_Boolean aResult = Standard_False;
372   GEOM::GEOM_Object_var anObj =
373     GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult);
374   if (aResult && !anObj->_is_nil() && GEOMBase::IsShape(anObj)) {
375     if (!anObj->_is_equivalent(myMainObj) && !anObj->_is_equivalent(myGroup)) {
376       SUIT_OverrideCursor wc;
377       myEditCurrentArgument->setText(GEOMBase::GetName(anObj));
378       GEOM::GEOM_IShapesOperations_var aShapesOp =
379         getGeomEngine()->GetIShapesOperations(getStudyId());
380       if ( subSelectionWay() == GET_IN_PLACE ) {
381         GEOM::GEOM_Object_var aGetInPlaceObj = aShapesOp->GetInPlace(myMainObj, anObj);
382         setInPlaceObj( aGetInPlaceObj );
383       }
384       else {
385         setInPlaceObj( anObj );
386       }
387       myEditCurrentArgument = 0;
388       //myBusy = true; // just activate but do not select in the list
389       activateSelection();
390       //myBusy = false;
391     }
392   }
393 }
394
395 //=======================================================================
396 //function : setInPlaceObj
397 //purpose  : temporarily add an object to study and remove old InPlaceObj
398 //=======================================================================
399
400 void GroupGUI_GroupDlg::setInPlaceObj( GEOM::GEOM_Object_var theObj )
401 {
402   if ( ! myInPlaceObj->_is_equivalent( theObj ) )
403   {
404     const char* tmpName = "__InPlaceObj__";
405     // remove old InPlaceObj
406     if ( !myInPlaceObj->_is_nil() ) {
407       if ( myInPlaceObjSelectWay == GET_IN_PLACE ) { // hide temporary object
408         GEOM_Displayer aDisplayer(getStudy());
409         aDisplayer.Erase( myInPlaceObj, true );
410       }
411       if (_PTR(SObject) SO = getStudy()->studyDS()->FindObject( tmpName )) {
412         getStudy()->studyDS()->NewBuilder()->RemoveObjectWithChildren( SO );
413         getGeomEngine()->RemoveObject(myInPlaceObj);
414       }
415     }
416     // publish InPlaceObj to enable localSelection(InPlaceObj)
417     if ( !theObj->_is_nil() && subSelectionWay() == GET_IN_PLACE ) {
418       SALOMEDS::Study_var aStudyDS = GeometryGUI::ClientStudyToStudy(getStudy()->studyDS());
419       SALOMEDS::SObject_var aSO =
420         getGeomEngine()->AddInStudy(aStudyDS, theObj, tmpName, myMainObj);
421     }
422     myInPlaceObj = theObj;
423   }
424   // build map of indices
425   myMain2InPlaceIndices.Clear();
426   if ( !myInPlaceObj->_is_nil() ) {
427     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
428     GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
429
430     GEOM::ListOfGO_var aSubObjects = aShapesOp->MakeExplode( myInPlaceObj, getShapeType(), false);
431     for (int i = 0; i < aSubObjects->length(); i++)
432     {
433       CORBA::Long aMainIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
434       CORBA::Long aPlaceIndex = aLocOp->GetSubShapeIndex( myInPlaceObj, aSubObjects[i] );
435       if ( aMainIndex >= 0 && aPlaceIndex > 0)
436         myMain2InPlaceIndices.Bind( aMainIndex, aPlaceIndex );
437     }
438   }
439   myInPlaceObjSelectWay = subSelectionWay();
440 }
441
442 //=================================================================================
443 // function : SelectionIntoArgument()
444 // purpose  : Called when selection has changed
445 //=================================================================================
446 void GroupGUI_GroupDlg::SelectionIntoArgument()
447 {
448 //   if (myPlaceCheckBox->isChecked() && myEditCurrentArgument == myShape2Name )
449   if (subSelectionWay() != ALL_SUBSHAPES && myEditCurrentArgument == myShape2Name) {
450     onGetInPlace();
451     return;
452   }
453
454   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
455   SALOME_ListIO aSelList;
456   aSelMgr->selectedObjects(aSelList);
457
458   if (myEditCurrentArgument == myMainName) {  // Selection of a main shape is active
459     myEditCurrentArgument->setText("");
460     myIdList->clear();
461
462     if (aSelList.Extent() == 1) {
463       Standard_Boolean aResult = Standard_False;
464       GEOM::GEOM_Object_var anObj =
465         GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult);
466
467       if ( aResult && !anObj->_is_nil() && GEOMBase::IsShape( anObj ) ) {
468         myMainObj = anObj;
469         myEditCurrentArgument->setText( GEOMBase::GetName( anObj ) );
470         // activate subshapes selection by default
471         myEditCurrentArgument = 0;
472         activateSelection();
473         updateState();
474         return;
475       }
476     }
477
478     myMainObj = GEOM::GEOM_Object::_nil();
479   }
480   else { // an attempt to synchronize list box selection with 3d viewer
481     if ( myBusy ) {
482       return;
483     }
484
485     bool isBlocked = myIdList->signalsBlocked();
486     myIdList->blockSignals( true );
487     myIdList->clearSelection();
488
489     TColStd_IndexedMapOfInteger aMapIndex;
490
491     LightApp_SelectionMgr::MapEntryOfMapOfInteger aMap;
492     aSelMgr->selectedSubOwners( aMap );
493     if ( aMap.Size() == 1 )
494       aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value();
495     bool subselected = aMapIndex.Extent();
496
497     // convert inPlace indices to main indices
498     //if ( subselected && myPlaceCheckBox->isChecked() )
499     if ( subselected && subSelectionWay() != ALL_SUBSHAPES )
500     {
501       TColStd_IndexedMapOfInteger aMapIndex2;
502       
503       TColStd_DataMapIteratorOfDataMapOfIntegerInteger m2ip( myMain2InPlaceIndices );
504       for ( ; m2ip.More(); m2ip.Next() ) {
505         int inPlaceId = m2ip.Value();
506         if ( aMapIndex.Contains( inPlaceId )) {
507           aMapIndex2.Add( m2ip.Key() );
508         }
509       }
510       aMapIndex = aMapIndex2;
511     }
512
513     // try to find out and process the object browser selection
514     if ( !subselected ) {
515       globalSelection( GEOM_ALLSHAPES );
516
517       GEOM::ListOfGO anObjects;
518       GEOMBase::ConvertListOfIOInListOfGO(aSelList, anObjects);
519
520       GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
521       GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
522
523       for (int i = 0; i < anObjects.length(); i++)
524       {
525         GEOM::GEOM_Object_var aGeomObj = anObjects[i];
526         GEOM::ListOfGO_var aSubObjects = new GEOM::ListOfGO();
527         TopoDS_Shape aShape;
528         if ( GEOMBase::GetShape(aGeomObj, aShape, getShapeType()) )
529         {
530           aSubObjects->length(1);
531           aSubObjects[0] = aGeomObj;
532         }
533         else if (aGeomObj->GetType() == GEOM_GROUP)
534           aSubObjects = aShapesOp->MakeExplode( aGeomObj, getShapeType(), false);
535         else
536           continue;
537
538         for (int i = 0; i < aSubObjects->length(); i++)
539         {
540           TopoDS_Shape aShape;
541           if ( GEOMBase::GetShape(aSubObjects[i], aShape, getShapeType()) )
542           {
543             CORBA::Long anIndex;
544             anIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
545             if ( anIndex >= 0 ) {
546               //if ( myPlaceCheckBox->isChecked() && ! myMain2InPlaceIndices.IsBound( anIndex ))
547               if ( subSelectionWay() != ALL_SUBSHAPES &&
548                    ! myMain2InPlaceIndices.IsBound( anIndex ))
549                 continue;
550               aMapIndex.Add( anIndex );
551             }
552           }
553         }
554       }
555       if ( !myMainObj->_is_nil() /*&& mySelSubBtn->isChecked()*/)
556         if ( subSelectionWay() == ALL_SUBSHAPES )
557           localSelection( myMainObj, getShapeType() );
558         else if ( !myInPlaceObj->_is_nil() )
559           localSelection( myInPlaceObj, getShapeType() );
560     }
561
562     if (aMapIndex.Extent() >= 1) {
563       QMap<int, int> aMap;
564       for ( int i = 0, n = myIdList->count(); i < n; i++ )
565         aMap.insert( myIdList->item( i )->text().toInt(), i );
566
567       for ( int ii = 1, nn = aMapIndex.Extent(); ii <= nn; ii++ ) {
568         if ( aMap.contains( aMapIndex( ii ) ) )
569           myIdList->item( aMap[aMapIndex( ii )])->setSelected( true );
570       }
571     }
572     myIdList->blockSignals( isBlocked );
573   }
574
575   updateState();
576 }
577
578 //=================================================================================
579 // function : ConstructorsClicked()
580 // purpose  : Radio button management
581 //=================================================================================
582 void GroupGUI_GroupDlg::ConstructorsClicked( int constructorId )
583 {
584   myIdList->clear();
585   activateSelection();
586   updateState();
587   setInPlaceObj( myInPlaceObj ); // to rebuild myMain2InPlaceIndices
588 }
589
590 //=================================================================================
591 // function : selectAllSubShapes
592 // purpose  : 
593 //=================================================================================
594 void GroupGUI_GroupDlg::selectAllSubShapes()
595 {
596   if ( CORBA::is_nil( myMainObj ) )
597     return;
598
599   GEOM::ListOfLong_var aSubShapes;
600 //   if ( !myPlaceCheckBox->isChecked() )
601   if ( subSelectionWay() == ALL_SUBSHAPES )
602   {
603     myIdList->clear();
604     GEOM::GEOM_IShapesOperations_var aShOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
605     aSubShapes = aShOp->SubShapeAllIDs(myMainObj, getShapeType(), false);
606
607     if ( !aShOp->IsDone() )
608       return;
609   }
610   else
611   {
612     aSubShapes = new GEOM::ListOfLong();
613     aSubShapes->length( myMain2InPlaceIndices.Extent() );
614     TColStd_DataMapIteratorOfDataMapOfIntegerInteger m2ip( myMain2InPlaceIndices );
615     for ( int i = 0; m2ip.More(); i++, m2ip.Next() )
616       aSubShapes[ i ] = m2ip.Key();
617   }
618   bool isBlocked = myIdList->signalsBlocked();
619   myIdList->blockSignals( true );
620
621   for ( int i = 0, n = aSubShapes->length(); i < n; i++ ) {
622     CORBA::Long anIndex = aSubShapes[i];
623     if ( anIndex < 0 )
624       continue;
625
626     QListWidgetItem* anItem = 0;
627     QString text = QString( "%1" ).arg( anIndex );
628     if ( !myInPlaceObj->_is_nil() ) {
629       QList<QListWidgetItem*> found = myIdList->findItems( text, Qt::MatchExactly );
630       if ( found.count() ) anItem = found[0];
631     }
632     if ( !anItem ) {
633       anItem = new QListWidgetItem( text );
634       myIdList->addItem( anItem );
635     }
636     anItem->setSelected( true );
637   }
638
639   myIdList->blockSignals( isBlocked );
640   highlightSubShapes();
641 }
642
643 //=================================================================================
644 // function : add
645 // purpose  : 
646 //=================================================================================
647 void GroupGUI_GroupDlg::add()
648 {
649   TColStd_MapOfInteger aMap;
650   for ( int i = 0, n = myIdList->count(); i < n; i++ )
651     aMap.Add( myIdList->item( i )->text().toInt() );
652
653   TColStd_IndexedMapOfInteger aMapIndex;
654
655   SALOME_ListIO aSelIOs;
656   SalomeApp_Application* app = myGeomGUI->getApp();
657   if ( app ) {
658     LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
659     if ( aSelMgr ) {
660       LightApp_SelectionMgr::MapEntryOfMapOfInteger aMap;
661       aSelMgr->selectedSubOwners( aMap );
662       if ( aMap.Size() == 1 )
663         aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value();
664     }
665   }
666   GEOM::ListOfGO anObjects;
667   // get selected sub-shapes of myInPlaceObj
668   if ( aMapIndex.Extent() > 0 && !myInPlaceObj->_is_nil() )
669   {
670     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
671
672     anObjects.length( aMapIndex.Extent() );
673     for ( int i = 1; i <= aMapIndex.Extent(); i++ )
674       anObjects[ i-1 ] = aShapesOp->GetSubShape( myInPlaceObj, aMapIndex( i ));
675
676     aMapIndex.Clear();
677   }
678
679   // try to find out and process the object browser selection or InPlace sub-shapes
680   if ( !aMapIndex.Extent() )
681   {
682     if ( anObjects.length() == 0 )
683       GEOMBase::ConvertListOfIOInListOfGO(aSelIOs, anObjects);
684
685     GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
686     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
687
688     for (int i = 0; i < anObjects.length(); i++)
689     {
690       GEOM::GEOM_Object_var aGeomObj = anObjects[i];
691       GEOM::ListOfGO_var aSubObjects  = new GEOM::ListOfGO();
692       TopoDS_Shape aShape;
693       if ( GEOMBase::GetShape(aGeomObj, aShape, getShapeType()) )
694       {
695         aSubObjects->length(1);
696         aSubObjects[0] = aGeomObj;
697       }
698       else if (aGeomObj->GetType() == GEOM_GROUP)
699         aSubObjects = aShapesOp->MakeExplode( aGeomObj, getShapeType(), false);
700       else
701         break;
702
703       for (int i = 0; i < aSubObjects->length(); i++)
704       {
705         TopoDS_Shape aShape;
706         if ( GEOMBase::GetShape(aSubObjects[i], aShape, getShapeType()) )
707         {
708           CORBA::Long anIndex;
709             anIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
710           if ( anIndex >= 0 )
711             aMapIndex.Add( anIndex );
712         }
713       }
714     }
715   }
716
717   if ( aMapIndex.Extent() >= 1 ) {
718     bool isBlocked = myIdList->signalsBlocked();
719     myIdList->blockSignals( true );
720
721     for ( int i = 1, n = aMapIndex.Extent(); i <= n; i++ ) {
722       if ( aMap.Contains( aMapIndex( i ) ) )
723         continue;
724
725       QListWidgetItem* anItem = new QListWidgetItem( QString( "%1" ).arg( aMapIndex( i ) ) );
726       myIdList->addItem( anItem );
727       anItem->setSelected( true );
728     }
729
730     myIdList->blockSignals( isBlocked );
731   }
732
733   updateState();
734 }
735
736 //=================================================================================
737 // function : remove
738 // purpose  : 
739 //=================================================================================
740 void GroupGUI_GroupDlg::remove()
741 {
742   bool isBlocked = myIdList->signalsBlocked();
743   myIdList->blockSignals( true );
744
745   QListIterator<QListWidgetItem*> it( myIdList->selectedItems() );
746   while ( it.hasNext() )
747     delete it.next();
748
749   myIdList->blockSignals( isBlocked );
750
751   highlightSubShapes();
752 }
753
754 //=======================================================================
755 //function : subSelectionWay
756 //purpose  : 
757 //=======================================================================
758
759 int GroupGUI_GroupDlg::subSelectionWay() const
760 {
761   return mySelectionWayGroup->checkedId();
762 }
763
764 //=================================================================================
765 // function : getShapeType()
766 // purpose  :
767 //=================================================================================
768 TopAbs_ShapeEnum GroupGUI_GroupDlg::getShapeType() const
769 {
770   switch ( getConstructorId() ) {
771   case 0:  return TopAbs_VERTEX;
772   case 1:  return TopAbs_EDGE;
773   case 2:  return TopAbs_FACE;
774   case 3:  return TopAbs_SOLID;
775   default: return TopAbs_SHAPE;
776   }
777 }
778
779 //=================================================================================
780 // function : setShapeType()
781 // purpose  :
782 //=================================================================================
783 void GroupGUI_GroupDlg::setShapeType( const TopAbs_ShapeEnum theType )
784 {
785   int anId = 0;
786   switch ( theType ) {
787   case TopAbs_VERTEX: anId = 0; break;
788   case TopAbs_EDGE:   anId = 1; break;
789   case TopAbs_FACE:   anId = 2; break;
790   case TopAbs_SOLID:  anId = 3; break;
791   }
792   setConstructorId( anId );
793 }
794
795
796 //=================================================================================
797 // function : activateSelection
798 // purpose  : Activate selection in accordance with myEditCurrentArgument
799 //=================================================================================
800 void GroupGUI_GroupDlg::activateSelection()
801 {
802   globalSelection( GEOM_ALLSHAPES );
803
804   // local selection
805   if ( !myMainObj->_is_nil() && !myEditCurrentArgument/* && mySelSubBtn->isChecked()*/) {
806 //     if ( !myPlaceCheckBox->isChecked() )
807     if ( subSelectionWay() == ALL_SUBSHAPES )
808       localSelection( myMainObj, getShapeType() );
809     else if ( !myInPlaceObj->_is_nil() )
810       localSelection( myInPlaceObj, getShapeType() );
811   }
812
813   SelectionIntoArgument();
814 }
815
816 //=================================================================================
817 // function : updateState
818 // purpose  : 
819 //=================================================================================
820 void GroupGUI_GroupDlg::updateState()
821 {
822   bool isAdd = false;
823
824   TColStd_IndexedMapOfInteger aMapIndex;
825
826   SALOME_ListIO aSelIOs;
827   SalomeApp_Application* app = myGeomGUI->getApp();
828   if ( app ) {
829     LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
830     if ( aSelMgr ) {
831       LightApp_SelectionMgr::MapEntryOfMapOfInteger aMap;
832       aSelMgr->selectedSubOwners( aMap );
833       if ( aMap.Size() == 1 )
834         aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value();
835     }
836   }
837
838   // try to find out and process the object browser selection
839   if ( !aMapIndex.Extent() && !CORBA::is_nil( myMainObj ) ) {
840     GEOM::ListOfGO anObjects;
841     //GEOMBase::ConvertListOfIOInListOfGO(selectedIO(), anObjects);
842     GEOMBase::ConvertListOfIOInListOfGO(aSelIOs, anObjects);
843
844     GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
845     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
846
847     isAdd = true;
848
849     for (int i = 0; i < anObjects.length(); i++)
850     {
851       GEOM::GEOM_Object_var aGeomObj = anObjects[i];
852       GEOM::ListOfGO_var aSubObjects = new GEOM::ListOfGO();
853       TopoDS_Shape aShape;
854       if ( GEOMBase::GetShape(aGeomObj, aShape, getShapeType()) ) {
855         aSubObjects->length(1);
856         aSubObjects[0] = aGeomObj;
857       }
858       else if (aGeomObj->GetType() == GEOM_GROUP) {
859         aSubObjects = aShapesOp->MakeExplode( aGeomObj, getShapeType(), false);
860       }
861       else {
862         aMapIndex.Clear();
863         break;
864       }
865
866       for (int i = 0; i < aSubObjects->length(); i++)
867       {
868         TopoDS_Shape aShape;
869         aSubObjects[i];
870         if ( GEOMBase::GetShape(aSubObjects[i], aShape, getShapeType()) )
871         {
872           CORBA::Long anIndex;
873           anIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
874           if ( anIndex >= 0 )
875             aMapIndex.Add( anIndex );
876           else
877             isAdd = false;
878         }
879         else
880           isAdd = false;
881
882         if ( !isAdd ) {
883           aMapIndex.Clear();
884           break;
885         }
886       }
887       if ( !isAdd ) {
888         aMapIndex.Clear();
889         break;
890       }
891     }
892   }
893
894   isAdd = aMapIndex.Extent() > 0;
895
896   myAddBtn->setEnabled( !myEditCurrentArgument && !CORBA::is_nil( myMainObj ) && isAdd );
897   bool hasSel = myIdList->selectedItems().count() > 0;
898   myRemBtn->setEnabled( hasSel );
899   //mySelSubBtn->setEnabled( !CORBA::is_nil( myMainObj ) );
900   //myPlaceCheckBox->setEnabled( !CORBA::is_nil( myMainObj ) );
901   mySelectionWayGroupBox->setEnabled( !CORBA::is_nil( myMainObj ) );
902   mySelAllBtn->setEnabled( !CORBA::is_nil( myMainObj ) );
903 //   mySelBtn2->setEnabled( myPlaceCheckBox->isChecked() );
904 //   myShape2Name->setEnabled( myPlaceCheckBox->isChecked() );
905   mySelBtn2->setEnabled(    subSelectionWay() != ALL_SUBSHAPES );
906   myShape2Name->setEnabled( subSelectionWay() != ALL_SUBSHAPES );
907 //   if ( !myPlaceCheckBox->isChecked() )
908   if ( subSelectionWay() == ALL_SUBSHAPES )
909     setInPlaceObj( GEOM::GEOM_Object::_nil() );
910 }
911
912 //=================================================================================
913 // function : selectionChanged
914 // purpose  :
915 //=================================================================================
916 void GroupGUI_GroupDlg::selectionChanged()
917 {
918   highlightSubShapes();
919 }
920
921 //=================================================================================
922 // function : highlightSubShapes
923 // purpose  :
924 //=================================================================================
925 void GroupGUI_GroupDlg::highlightSubShapes()
926 {
927   if ( CORBA::is_nil( myMainObj ) )
928     return;
929
930   Standard_Boolean isOk;
931   char* objIOR;
932
933   if ( myInPlaceObj->_is_nil() )
934     objIOR = GEOMBase::GetIORFromObject( myMainObj );
935   else
936     objIOR = GEOMBase::GetIORFromObject( myInPlaceObj );
937
938   Handle(GEOM_AISShape) aSh = GEOMBase::ConvertIORinGEOMAISShape( objIOR, isOk, true );
939   free( objIOR );
940   if ( !isOk || aSh.IsNull() )
941     return;
942
943   TColStd_MapOfInteger anIds;
944
945   myBusy = true;
946
947   int ii = 0, nn = myIdList->count();
948   for ( ; ii < nn; ii++ )
949   {
950     if ( myIdList->item( ii )->isSelected() ) {
951       int id = myIdList->item( ii )->text().toInt();
952       //       if ( myPlaceCheckBox->isChecked() )
953       if ( subSelectionWay() != ALL_SUBSHAPES )
954       {
955         if ( myMain2InPlaceIndices.IsBound( id ) )
956           id = myMain2InPlaceIndices( id );
957         else {
958           myIdList->item( ii )->setSelected( false );
959           continue;
960         }
961       }
962       anIds.Add( id );
963     }
964   }
965   SalomeApp_Application* app = myGeomGUI->getApp();
966   LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
967   aSelMgr->clearSelected();
968
969   aSelMgr->AddOrRemoveIndex(aSh->getIO(), anIds, false);
970
971   myBusy = false;
972
973   if (nn < 3000)
974     updateState();
975   else {
976     myAddBtn->setEnabled( true );
977     myRemBtn->setEnabled( true );
978   }
979 }
980
981 //=================================================================================
982 // function : createOperation
983 // purpose  :
984 //=================================================================================
985 GEOM::GEOM_IOperations_ptr GroupGUI_GroupDlg::createOperation()
986 {
987   return getGeomEngine()->GetIGroupOperations( getStudyId() );
988 }
989
990 #define RETURN_WITH_MSG(a, b) \
991   if ( !(a) ) { \
992     theMessage += (b); \
993     return false; \
994   }
995
996 //=================================================================================
997 // function : isValid()
998 // purpose  : Verify validity of input data
999 //=================================================================================
1000 bool GroupGUI_GroupDlg::isValid( QString& theMessage )
1001 {
1002   SalomeApp_Study* study = getStudy();
1003   ASSERT(study);
1004   RETURN_WITH_MSG  ( !study->studyDS()->GetProperties()->IsLocked(), tr( "GEOM_STUDY_LOCKED" ) )
1005
1006   if ( myMode == CreateGroup ) {
1007     RETURN_WITH_MSG( !CORBA::is_nil( myMainObj ), tr( "NO_MAIN_OBJ" ) )
1008   }
1009   else {
1010     RETURN_WITH_MSG( !CORBA::is_nil( myMainObj ), tr( "NO_GROUP" ) )
1011   }
1012
1013   QString aName (getNewObjectName());
1014   RETURN_WITH_MSG  ( !aName.trimmed().isEmpty(), tr( "EMPTY_NAME" ) )
1015
1016   RETURN_WITH_MSG  ( myIdList->count(), tr( "EMPTY_LIST" ) )
1017   return true;
1018 }
1019
1020 //=================================================================================
1021 // function : execute
1022 // purpose  :
1023 //=================================================================================
1024 bool GroupGUI_GroupDlg::execute( ObjectList& objects )
1025 {
1026   setInPlaceObj( GEOM::GEOM_Object::_nil() );
1027
1028   GEOM::GEOM_IGroupOperations_var anOp = GEOM::GEOM_IGroupOperations::_narrow(getOperation());
1029
1030   GEOM::GEOM_Object_var aGroup;
1031   if (myMode == CreateGroup)
1032     aGroup = anOp->CreateGroup(myMainObj, getShapeType());
1033   else if (myMode == EditGroup)
1034     aGroup = myGroup;
1035
1036   if (CORBA::is_nil(aGroup) || (myMode == CreateGroup && !anOp->IsDone()))
1037     return false;
1038
1039   GEOM::ListOfLong_var aCurrList = anOp->GetObjects(aGroup);
1040   if (!anOp->IsDone())
1041     return false;
1042
1043   if (aCurrList->length() > 0)
1044   {
1045     anOp->DifferenceIDs(aGroup, aCurrList);
1046     if (!anOp->IsDone())
1047       return false;
1048   }
1049
1050   int ii, nn = myIdList->count();
1051   if (nn > 0)
1052   {
1053     GEOM::ListOfLong_var aNewList = new GEOM::ListOfLong;
1054     aNewList->length(nn);
1055     for (ii = 0; ii < nn; ii++) {
1056       aNewList[ii] = myIdList->item(ii)->text().toInt();
1057     }
1058     anOp->UnionIDs(aGroup, aNewList);
1059     if (!anOp->IsDone())
1060       return false;
1061   }
1062
1063   SalomeApp_Study* study = getStudy();
1064   if ( study ) {
1065     char* objIOR = GEOMBase::GetIORFromObject( aGroup );
1066     std::string IOR( objIOR );
1067     free( objIOR );
1068     if ( IOR != "" ) {
1069       _PTR(SObject) SO ( study->studyDS()->FindObjectIOR( IOR ) );
1070       if ( SO ) {
1071         _PTR(StudyBuilder) aBuilder (study->studyDS()->NewBuilder());
1072         aBuilder->SetName( SO, getNewObjectName().toLatin1().constData() );
1073       }
1074     }
1075   }
1076
1077   objects.push_back( aGroup._retn() );
1078
1079   return true;
1080 }
1081
1082 //================================================================
1083 // Function : getFather
1084 // Purpose  : Get father object for object to be added in study
1085 //            ( called with addInStudy method )
1086 //================================================================
1087 GEOM::GEOM_Object_ptr GroupGUI_GroupDlg::getFather( GEOM::GEOM_Object_ptr theObj )
1088 {
1089   GEOM::GEOM_Object_var aFatherObj;
1090   if ( theObj->GetType() == GEOM_GROUP ) {
1091     GEOM::GEOM_IGroupOperations_var anOp = GEOM::GEOM_IGroupOperations::_narrow( getOperation() );
1092     aFatherObj = anOp->GetMainShape( theObj );
1093   }
1094   return aFatherObj._retn();
1095 }