]> SALOME platform Git repositories - modules/geom.git/blob - src/GroupGUI/GroupGUI_GroupDlg.cxx
Salome HOME
ac3e610e3f765b590d932d03dd92227b9b082aab
[modules/geom.git] / src / GroupGUI / GroupGUI_GroupDlg.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   : GroupGUI_GroupDlg.cxx
24 // Author : Sergey ANIKIN, Open CASCADE S.A.S. (sergey.anikin@opencascade.com)
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, SUBSHAPES_OF_INVISIBLE_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( itemSelectionChanged() ),   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       ConstructorsClicked( getConstructorId() );
272     }
273   else
274     activateSelection();
275   return true;
276 }
277
278 //=================================================================================
279 // function : ActivateThisDialog()
280 // purpose  :
281 //=================================================================================
282 void GroupGUI_GroupDlg::ActivateThisDialog()
283 {
284   GEOMBase_Skeleton::ActivateThisDialog();
285
286   connect( ((SalomeApp_Application*)(SUIT_Session::session()->activeApplication()))->selectionMgr(),
287            SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) );
288
289   activateSelection();
290 }
291
292 //=================================================================================
293 // function : LineEditReturnPressed()
294 // purpose  :
295 //=================================================================================
296 void GroupGUI_GroupDlg::LineEditReturnPressed()
297 {
298   QLineEdit* send = ( QLineEdit* )sender();
299
300   if ( send == myMainName && !myEditCurrentArgument ) {
301     myEditCurrentArgument = myMainName;
302     activateSelection();
303   }
304   else
305     GEOMBase_Skeleton::LineEditReturnPressed();
306
307   updateState();
308 }
309
310 //=================================================================================
311 // function : SetEditCurrentArgument()
312 // purpose  :
313 //=================================================================================
314 void GroupGUI_GroupDlg::SetEditCurrentArgument()
315 {
316   QPushButton* send = (QPushButton*)sender();
317
318   if ( send == mySelBtn ) {
319     myEditCurrentArgument = myMainName;
320     myShape2Name->setText( "" );
321   }
322   else if ( /*(QRadioButton*)sender() == mySelSubBtn ||*/ send == mySelAllBtn )
323     myEditCurrentArgument = 0;
324   else if ( send == mySelBtn2 || sender() == mySelectionWayGroup ) {
325     setInPlaceObj( GEOM::GEOM_Object::_nil() );
326     //if ( myPlaceCheckBox->isChecked() )
327     myShape2Name->setText( "" );
328     if ( subSelectionWay() != ALL_SUBSHAPES )
329     {
330       myEditCurrentArgument = myShape2Name;
331     }
332     else {
333       //myEditCurrentArgument = myMainName;
334       myEditCurrentArgument = 0;
335     }
336   }
337
338   activateSelection();
339
340   if ( send == mySelAllBtn ) {
341 //     myShape2Name->setText( "" );
342 //     myPlaceCheckBox->setChecked( false );
343 //     mySelBtn2->setEnabled( false );
344 //     myShape2Name->setEnabled( false );
345     selectAllSubShapes();
346   }
347   else
348     updateState();
349 }
350
351 //=================================================================================
352 // function : onGetInPlace()
353 // purpose  :
354 //=================================================================================
355 void GroupGUI_GroupDlg::onGetInPlace()
356 {
357   setInPlaceObj( GEOM::GEOM_Object::_nil() );
358   myEditCurrentArgument->setText( "" );
359
360   bool isBlocked = myIdList->signalsBlocked();
361   myIdList->blockSignals( true );
362   myIdList->clearSelection();
363   myIdList->blockSignals( isBlocked );
364
365   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
366   SALOME_ListIO aSelList;
367   aSelMgr->selectedObjects(aSelList);
368
369   if (aSelList.Extent() != 1)
370     return;
371
372   Standard_Boolean aResult = Standard_False;
373   GEOM::GEOM_Object_var anObj =
374     GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult);
375   if (aResult && !anObj->_is_nil() && GEOMBase::IsShape(anObj)) {
376     if (!anObj->_is_equivalent(myMainObj) && !anObj->_is_equivalent(myGroup)) {
377       SUIT_OverrideCursor wc;
378       myEditCurrentArgument->setText(GEOMBase::GetName(anObj));
379       GEOM::GEOM_IShapesOperations_var aShapesOp =
380         getGeomEngine()->GetIShapesOperations(getStudyId());
381       if ( subSelectionWay() == GET_IN_PLACE ) {
382         GEOM::GEOM_Object_var aGetInPlaceObj = aShapesOp->GetInPlace(myMainObj, anObj);
383         setInPlaceObj( aGetInPlaceObj );
384       }
385       else {
386         bool isVisible = true;
387         if ( SALOME_View* view = GEOM_Displayer::GetActiveView() )
388           isVisible = view->isVisible( aSelList.First() );
389         setInPlaceObj( anObj, isVisible );
390       }
391       myEditCurrentArgument = 0;
392       //myBusy = true; // just activate but do not select in the list
393       activateSelection();
394       //myBusy = false;
395     }
396   }
397 }
398
399 //=======================================================================
400 //function : setInPlaceObj
401 //purpose  : temporarily add an object to study and remove old InPlaceObj
402 //=======================================================================
403
404 void GroupGUI_GroupDlg::setInPlaceObj( GEOM::GEOM_Object_var theObj, const bool isVisible )
405 {
406   if ( ! myInPlaceObj->_is_equivalent( theObj ) )
407   {
408     const char* tmpName = "__InPlaceObj__";
409     // remove old InPlaceObj
410     if ( !myInPlaceObj->_is_nil() ) {
411       if ( myInPlaceObjSelectState == GET_IN_PLACE ||
412            myInPlaceObjSelectState == SUBSHAPES_OF_INVISIBLE_SHAPE2 ) {
413         // hide temporary object or initially invisible shape 2 (issue 0014047)
414         GEOM_Displayer aDisplayer(getStudy());
415         aDisplayer.Erase( myInPlaceObj, true );
416       }
417       if (_PTR(SObject) SO = getStudy()->studyDS()->FindObject( tmpName )) {
418         getStudy()->studyDS()->NewBuilder()->RemoveObjectWithChildren( SO );
419         getGeomEngine()->RemoveObject(myInPlaceObj);
420       }
421     }
422     // publish InPlaceObj to enable localSelection(InPlaceObj)
423     if ( !theObj->_is_nil() && subSelectionWay() == GET_IN_PLACE ) {
424       SALOMEDS::Study_var aStudyDS = GeometryGUI::ClientStudyToStudy(getStudy()->studyDS());
425       SALOMEDS::SObject_var aSO =
426         getGeomEngine()->AddInStudy(aStudyDS, theObj, tmpName, myMainObj);
427     }
428     myInPlaceObj = theObj;
429   }
430   // build map of indices
431   myMain2InPlaceIndices.Clear();
432   if ( !myInPlaceObj->_is_nil() ) {
433     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
434     GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
435
436     GEOM::ListOfGO_var aSubObjects = aShapesOp->MakeExplode( myInPlaceObj, getShapeType(), false);
437     for (int i = 0; i < aSubObjects->length(); i++)
438     {
439       CORBA::Long aMainIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
440       CORBA::Long aPlaceIndex = aLocOp->GetSubShapeIndex( myInPlaceObj, aSubObjects[i] );
441       if ( aMainIndex >= 0 && aPlaceIndex > 0)
442         myMain2InPlaceIndices.Bind( aMainIndex, aPlaceIndex );
443     }
444   }
445   myInPlaceObjSelectState = subSelectionWay();
446   if ( myInPlaceObjSelectState == SUBSHAPES_OF_SHAPE2 && !isVisible )
447     myInPlaceObjSelectState = SUBSHAPES_OF_INVISIBLE_SHAPE2;
448 }
449
450 //=================================================================================
451 // function : SelectionIntoArgument()
452 // purpose  : Called when selection has changed
453 //=================================================================================
454 void GroupGUI_GroupDlg::SelectionIntoArgument()
455 {
456 //   if (myPlaceCheckBox->isChecked() && myEditCurrentArgument == myShape2Name )
457   if (subSelectionWay() != ALL_SUBSHAPES && myEditCurrentArgument == myShape2Name) {
458     onGetInPlace();
459     return;
460   }
461
462   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
463   SALOME_ListIO aSelList;
464   aSelMgr->selectedObjects(aSelList);
465
466   if (myEditCurrentArgument == myMainName) {  // Selection of a main shape is active
467     myEditCurrentArgument->setText("");
468     myIdList->clear();
469
470     if (aSelList.Extent() == 1) {
471       Standard_Boolean aResult = Standard_False;
472       GEOM::GEOM_Object_var anObj =
473         GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult);
474
475       if ( aResult && !anObj->_is_nil() && GEOMBase::IsShape( anObj ) ) {
476         myMainObj = anObj;
477         myEditCurrentArgument->setText( GEOMBase::GetName( anObj ) );
478         // activate subshapes selection by default
479         myEditCurrentArgument = 0;
480         activateSelection();
481         updateState();
482         return;
483       }
484     }
485
486     myMainObj = GEOM::GEOM_Object::_nil();
487   }
488   else { // an attempt to synchronize list box selection with 3d viewer
489     if ( myBusy ) {
490       return;
491     }
492
493     bool isBlocked = myIdList->signalsBlocked();
494     myIdList->blockSignals( true );
495     myIdList->clearSelection();
496
497     TColStd_IndexedMapOfInteger aMapIndex;
498
499     LightApp_SelectionMgr::MapEntryOfMapOfInteger aMap;
500     aSelMgr->selectedSubOwners( aMap );
501     if ( aMap.Size() == 1 )
502       aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value();
503     bool subselected = aMapIndex.Extent();
504
505     // convert inPlace indices to main indices
506     //if ( subselected && myPlaceCheckBox->isChecked() )
507     if ( subselected && subSelectionWay() != ALL_SUBSHAPES )
508     {
509       TColStd_IndexedMapOfInteger aMapIndex2;
510       
511       TColStd_DataMapIteratorOfDataMapOfIntegerInteger m2ip( myMain2InPlaceIndices );
512       for ( ; m2ip.More(); m2ip.Next() ) {
513         int inPlaceId = m2ip.Value();
514         if ( aMapIndex.Contains( inPlaceId )) {
515           aMapIndex2.Add( m2ip.Key() );
516         }
517       }
518       aMapIndex = aMapIndex2;
519     }
520
521     // try to find out and process the object browser selection
522     if ( !subselected ) {
523       globalSelection( GEOM_ALLSHAPES );
524
525       GEOM::ListOfGO anObjects;
526       GEOMBase::ConvertListOfIOInListOfGO(aSelList, anObjects);
527
528       GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
529       GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
530
531       for (int i = 0; i < anObjects.length(); i++)
532       {
533         GEOM::GEOM_Object_var aGeomObj = anObjects[i];
534         GEOM::ListOfGO_var aSubObjects = new GEOM::ListOfGO();
535         TopoDS_Shape aShape;
536         if ( GEOMBase::GetShape(aGeomObj, aShape, getShapeType()) )
537         {
538           aSubObjects->length(1);
539           aSubObjects[0] = aGeomObj;
540         }
541         else if (aGeomObj->GetType() == GEOM_GROUP)
542           aSubObjects = aShapesOp->MakeExplode( aGeomObj, getShapeType(), false);
543         else
544           continue;
545
546         for (int i = 0; i < aSubObjects->length(); i++)
547         {
548           TopoDS_Shape aShape;
549           if ( GEOMBase::GetShape(aSubObjects[i], aShape, getShapeType()) )
550           {
551             CORBA::Long anIndex;
552             anIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
553             if ( anIndex >= 0 ) {
554               //if ( myPlaceCheckBox->isChecked() && ! myMain2InPlaceIndices.IsBound( anIndex ))
555               if ( subSelectionWay() != ALL_SUBSHAPES &&
556                    ! myMain2InPlaceIndices.IsBound( anIndex ))
557                 continue;
558               aMapIndex.Add( anIndex );
559             }
560           }
561         }
562       }
563       if ( !myMainObj->_is_nil() /*&& mySelSubBtn->isChecked()*/)
564         if ( subSelectionWay() == ALL_SUBSHAPES )
565           localSelection( myMainObj, getShapeType() );
566         else if ( !myInPlaceObj->_is_nil() )
567           localSelection( myInPlaceObj, getShapeType() );
568     }
569
570     if (aMapIndex.Extent() >= 1) {
571       QMap<int, int> aMap;
572       for ( int i = 0, n = myIdList->count(); i < n; i++ )
573         aMap.insert( myIdList->item( i )->text().toInt(), i );
574
575       for ( int ii = 1, nn = aMapIndex.Extent(); ii <= nn; ii++ ) {
576         if ( aMap.contains( aMapIndex( ii ) ) )
577           myIdList->item( aMap[aMapIndex( ii )])->setSelected( true );
578       }
579     }
580     myIdList->blockSignals( isBlocked );
581   }
582
583   updateState();
584 }
585
586 //=================================================================================
587 // function : ConstructorsClicked()
588 // purpose  : Radio button management
589 //=================================================================================
590 void GroupGUI_GroupDlg::ConstructorsClicked( int constructorId )
591 {
592   myIdList->clear();
593   activateSelection();
594   updateState();
595   setInPlaceObj( myInPlaceObj ); // to rebuild myMain2InPlaceIndices
596 }
597
598 //=================================================================================
599 // function : selectAllSubShapes
600 // purpose  : 
601 //=================================================================================
602 void GroupGUI_GroupDlg::selectAllSubShapes()
603 {
604   if ( CORBA::is_nil( myMainObj ) )
605     return;
606
607   GEOM::ListOfLong_var aSubShapes;
608 //   if ( !myPlaceCheckBox->isChecked() )
609   if ( subSelectionWay() == ALL_SUBSHAPES )
610   {
611     myIdList->clear();
612     GEOM::GEOM_IShapesOperations_var aShOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
613     aSubShapes = aShOp->SubShapeAllIDs(myMainObj, getShapeType(), false);
614
615     if ( !aShOp->IsDone() )
616       return;
617   }
618   else
619   {
620     aSubShapes = new GEOM::ListOfLong();
621     aSubShapes->length( myMain2InPlaceIndices.Extent() );
622     TColStd_DataMapIteratorOfDataMapOfIntegerInteger m2ip( myMain2InPlaceIndices );
623     for ( int i = 0; m2ip.More(); i++, m2ip.Next() )
624       aSubShapes[ i ] = m2ip.Key();
625   }
626   bool isBlocked = myIdList->signalsBlocked();
627   myIdList->blockSignals( true );
628
629   for ( int i = 0, n = aSubShapes->length(); i < n; i++ ) {
630     CORBA::Long anIndex = aSubShapes[i];
631     if ( anIndex < 0 )
632       continue;
633
634     QListWidgetItem* anItem = 0;
635     QString text = QString( "%1" ).arg( anIndex );
636     if ( !myInPlaceObj->_is_nil() ) {
637       QList<QListWidgetItem*> found = myIdList->findItems( text, Qt::MatchExactly );
638       if ( found.count() ) anItem = found[0];
639     }
640     if ( !anItem ) {
641       anItem = new QListWidgetItem( text );
642       myIdList->addItem( anItem );
643     }
644     anItem->setSelected( true );
645   }
646
647   myIdList->blockSignals( isBlocked );
648   highlightSubShapes();
649 }
650
651 //=================================================================================
652 // function : add
653 // purpose  : 
654 //=================================================================================
655 void GroupGUI_GroupDlg::add()
656 {
657   TColStd_MapOfInteger aMap;
658   for ( int i = 0, n = myIdList->count(); i < n; i++ )
659     aMap.Add( myIdList->item( i )->text().toInt() );
660
661   TColStd_IndexedMapOfInteger aMapIndex;
662
663   SALOME_ListIO aSelIOs;
664   SalomeApp_Application* app = myGeomGUI->getApp();
665   if ( app ) {
666     LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
667     if ( aSelMgr ) {
668       LightApp_SelectionMgr::MapEntryOfMapOfInteger aMap;
669       aSelMgr->selectedSubOwners( aMap );
670       if ( aMap.Size() == 1 )
671         aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value();
672     }
673   }
674   GEOM::ListOfGO anObjects;
675   // get selected sub-shapes of myInPlaceObj
676   if ( aMapIndex.Extent() > 0 && !myInPlaceObj->_is_nil() )
677   {
678     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
679
680     anObjects.length( aMapIndex.Extent() );
681     for ( int i = 1; i <= aMapIndex.Extent(); i++ )
682       anObjects[ i-1 ] = aShapesOp->GetSubShape( myInPlaceObj, aMapIndex( i ));
683
684     aMapIndex.Clear();
685   }
686
687   // try to find out and process the object browser selection or InPlace sub-shapes
688   if ( !aMapIndex.Extent() )
689   {
690     if ( anObjects.length() == 0 )
691       GEOMBase::ConvertListOfIOInListOfGO(aSelIOs, anObjects);
692
693     GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
694     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
695
696     for (int i = 0; i < anObjects.length(); i++)
697     {
698       GEOM::GEOM_Object_var aGeomObj = anObjects[i];
699       GEOM::ListOfGO_var aSubObjects  = new GEOM::ListOfGO();
700       TopoDS_Shape aShape;
701       if ( GEOMBase::GetShape(aGeomObj, aShape, getShapeType()) )
702       {
703         aSubObjects->length(1);
704         aSubObjects[0] = aGeomObj;
705       }
706       else if (aGeomObj->GetType() == GEOM_GROUP)
707         aSubObjects = aShapesOp->MakeExplode( aGeomObj, getShapeType(), false);
708       else
709         break;
710
711       for (int i = 0; i < aSubObjects->length(); i++)
712       {
713         TopoDS_Shape aShape;
714         if ( GEOMBase::GetShape(aSubObjects[i], aShape, getShapeType()) )
715         {
716           CORBA::Long anIndex;
717             anIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
718           if ( anIndex >= 0 )
719             aMapIndex.Add( anIndex );
720         }
721       }
722     }
723   }
724
725   if ( aMapIndex.Extent() >= 1 ) {
726     bool isBlocked = myIdList->signalsBlocked();
727     myIdList->blockSignals( true );
728
729     for ( int i = 1, n = aMapIndex.Extent(); i <= n; i++ ) {
730       if ( aMap.Contains( aMapIndex( i ) ) )
731         continue;
732
733       QListWidgetItem* anItem = new QListWidgetItem( QString( "%1" ).arg( aMapIndex( i ) ) );
734       myIdList->addItem( anItem );
735       anItem->setSelected( true );
736     }
737
738     myIdList->blockSignals( isBlocked );
739   }
740
741   updateState();
742 }
743
744 //=================================================================================
745 // function : remove
746 // purpose  : 
747 //=================================================================================
748 void GroupGUI_GroupDlg::remove()
749 {
750   bool isBlocked = myIdList->signalsBlocked();
751   myIdList->blockSignals( true );
752
753   QListIterator<QListWidgetItem*> it( myIdList->selectedItems() );
754   while ( it.hasNext() )
755     delete it.next();
756
757   myIdList->blockSignals( isBlocked );
758
759   highlightSubShapes();
760 }
761
762 //=======================================================================
763 //function : subSelectionWay
764 //purpose  : 
765 //=======================================================================
766
767 int GroupGUI_GroupDlg::subSelectionWay() const
768 {
769   return mySelectionWayGroup->checkedId();
770 }
771
772 //=================================================================================
773 // function : getShapeType()
774 // purpose  :
775 //=================================================================================
776 TopAbs_ShapeEnum GroupGUI_GroupDlg::getShapeType() const
777 {
778   switch ( getConstructorId() ) {
779   case 0:  return TopAbs_VERTEX;
780   case 1:  return TopAbs_EDGE;
781   case 2:  return TopAbs_FACE;
782   case 3:  return TopAbs_SOLID;
783   default: return TopAbs_SHAPE;
784   }
785 }
786
787 //=================================================================================
788 // function : setShapeType()
789 // purpose  :
790 //=================================================================================
791 void GroupGUI_GroupDlg::setShapeType( const TopAbs_ShapeEnum theType )
792 {
793   int anId = 0;
794   switch ( theType ) {
795   case TopAbs_VERTEX: anId = 0; break;
796   case TopAbs_EDGE:   anId = 1; break;
797   case TopAbs_FACE:   anId = 2; break;
798   case TopAbs_SOLID:  anId = 3; break;
799   }
800   setConstructorId( anId );
801 }
802
803
804 //=================================================================================
805 // function : activateSelection
806 // purpose  : Activate selection in accordance with myEditCurrentArgument
807 //=================================================================================
808 void GroupGUI_GroupDlg::activateSelection()
809 {
810   globalSelection( GEOM_ALLSHAPES );
811
812   // local selection
813   if ( !myMainObj->_is_nil() && !myEditCurrentArgument/* && mySelSubBtn->isChecked()*/) {
814 //     if ( !myPlaceCheckBox->isChecked() )
815     if ( subSelectionWay() == ALL_SUBSHAPES )
816       localSelection( myMainObj, getShapeType() );
817     else if ( !myInPlaceObj->_is_nil() )
818       localSelection( myInPlaceObj, getShapeType() );
819   }
820
821   SelectionIntoArgument();
822 }
823
824 //=================================================================================
825 // function : updateState
826 // purpose  : 
827 //=================================================================================
828 void GroupGUI_GroupDlg::updateState()
829 {
830   bool isAdd = false;
831
832   TColStd_IndexedMapOfInteger aMapIndex;
833
834   SALOME_ListIO aSelIOs;
835   SalomeApp_Application* app = myGeomGUI->getApp();
836   if ( app ) {
837     LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
838     if ( aSelMgr ) {
839       LightApp_SelectionMgr::MapEntryOfMapOfInteger aMap;
840       aSelMgr->selectedSubOwners( aMap );
841       if ( aMap.Size() == 1 )
842         aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value();
843     }
844   }
845
846   // try to find out and process the object browser selection
847   if ( !aMapIndex.Extent() && !CORBA::is_nil( myMainObj ) ) {
848     GEOM::ListOfGO anObjects;
849     //GEOMBase::ConvertListOfIOInListOfGO(selectedIO(), anObjects);
850     GEOMBase::ConvertListOfIOInListOfGO(aSelIOs, anObjects);
851
852     GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
853     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
854
855     isAdd = true;
856
857     for (int i = 0; i < anObjects.length(); i++)
858     {
859       GEOM::GEOM_Object_var aGeomObj = anObjects[i];
860       GEOM::ListOfGO_var aSubObjects = new GEOM::ListOfGO();
861       TopoDS_Shape aShape;
862       if ( GEOMBase::GetShape(aGeomObj, aShape, getShapeType()) ) {
863         aSubObjects->length(1);
864         aSubObjects[0] = aGeomObj;
865       }
866       else if (aGeomObj->GetType() == GEOM_GROUP) {
867         aSubObjects = aShapesOp->MakeExplode( aGeomObj, getShapeType(), false);
868       }
869       else {
870         aMapIndex.Clear();
871         break;
872       }
873
874       for (int i = 0; i < aSubObjects->length(); i++)
875       {
876         TopoDS_Shape aShape;
877         aSubObjects[i];
878         if ( GEOMBase::GetShape(aSubObjects[i], aShape, getShapeType()) )
879         {
880           CORBA::Long anIndex;
881           anIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
882           if ( anIndex >= 0 )
883             aMapIndex.Add( anIndex );
884           else
885             isAdd = false;
886         }
887         else
888           isAdd = false;
889
890         if ( !isAdd ) {
891           aMapIndex.Clear();
892           break;
893         }
894       }
895       if ( !isAdd ) {
896         aMapIndex.Clear();
897         break;
898       }
899     }
900   }
901
902   isAdd = aMapIndex.Extent() > 0;
903
904   myAddBtn->setEnabled( !myEditCurrentArgument && !CORBA::is_nil( myMainObj ) && isAdd );
905   bool hasSel = myIdList->selectedItems().count() > 0;
906   myRemBtn->setEnabled( hasSel );
907   //mySelSubBtn->setEnabled( !CORBA::is_nil( myMainObj ) );
908   //myPlaceCheckBox->setEnabled( !CORBA::is_nil( myMainObj ) );
909   mySelectionWayGroupBox->setEnabled( !CORBA::is_nil( myMainObj ) );
910   mySelAllBtn->setEnabled( !CORBA::is_nil( myMainObj ) );
911 //   mySelBtn2->setEnabled( myPlaceCheckBox->isChecked() );
912 //   myShape2Name->setEnabled( myPlaceCheckBox->isChecked() );
913   mySelBtn2->setEnabled(    subSelectionWay() != ALL_SUBSHAPES );
914   myShape2Name->setEnabled( subSelectionWay() != ALL_SUBSHAPES );
915 //   if ( !myPlaceCheckBox->isChecked() )
916   if ( subSelectionWay() == ALL_SUBSHAPES )
917     setInPlaceObj( GEOM::GEOM_Object::_nil() );
918 }
919
920 //=================================================================================
921 // function : selectionChanged
922 // purpose  :
923 //=================================================================================
924 void GroupGUI_GroupDlg::selectionChanged()
925 {
926   highlightSubShapes();
927 }
928
929 //=================================================================================
930 // function : highlightSubShapes
931 // purpose  :
932 //=================================================================================
933 void GroupGUI_GroupDlg::highlightSubShapes()
934 {
935   if ( CORBA::is_nil( myMainObj ) )
936     return;
937
938   Standard_Boolean isOk;
939   char* objIOR;
940
941   if ( myInPlaceObj->_is_nil() )
942     objIOR = GEOMBase::GetIORFromObject( myMainObj );
943   else
944     objIOR = GEOMBase::GetIORFromObject( myInPlaceObj );
945
946   Handle(GEOM_AISShape) aSh = GEOMBase::ConvertIORinGEOMAISShape( objIOR, isOk, true );
947   free( objIOR );
948   if ( !isOk || aSh.IsNull() )
949     return;
950
951   TColStd_MapOfInteger anIds;
952
953   myBusy = true;
954
955   int ii = 0, nn = myIdList->count();
956   for ( ; ii < nn; ii++ )
957   {
958     if ( myIdList->item( ii )->isSelected() ) {
959       int id = myIdList->item( ii )->text().toInt();
960       //       if ( myPlaceCheckBox->isChecked() )
961       if ( subSelectionWay() != ALL_SUBSHAPES )
962       {
963         if ( myMain2InPlaceIndices.IsBound( id ) )
964           id = myMain2InPlaceIndices( id );
965         else {
966           myIdList->item( ii )->setSelected( false );
967           continue;
968         }
969       }
970       anIds.Add( id );
971     }
972   }
973   SalomeApp_Application* app = myGeomGUI->getApp();
974   LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
975   aSelMgr->clearSelected();
976
977   aSelMgr->AddOrRemoveIndex(aSh->getIO(), anIds, false);
978
979   myBusy = false;
980
981   if (nn < 3000)
982     updateState();
983   else {
984     myAddBtn->setEnabled( true );
985     myRemBtn->setEnabled( true );
986   }
987 }
988
989 //=================================================================================
990 // function : createOperation
991 // purpose  :
992 //=================================================================================
993 GEOM::GEOM_IOperations_ptr GroupGUI_GroupDlg::createOperation()
994 {
995   return getGeomEngine()->GetIGroupOperations( getStudyId() );
996 }
997
998 #define RETURN_WITH_MSG(a, b) \
999   if ( !(a) ) { \
1000     theMessage += (b); \
1001     return false; \
1002   }
1003
1004 //=================================================================================
1005 // function : isValid()
1006 // purpose  : Verify validity of input data
1007 //=================================================================================
1008 bool GroupGUI_GroupDlg::isValid( QString& theMessage )
1009 {
1010   SalomeApp_Study* study = getStudy();
1011   ASSERT(study);
1012   RETURN_WITH_MSG  ( !study->studyDS()->GetProperties()->IsLocked(), tr( "GEOM_STUDY_LOCKED" ) )
1013
1014   if ( myMode == CreateGroup ) {
1015     RETURN_WITH_MSG( !CORBA::is_nil( myMainObj ), tr( "NO_MAIN_OBJ" ) )
1016   }
1017   else {
1018     RETURN_WITH_MSG( !CORBA::is_nil( myMainObj ), tr( "NO_GROUP" ) )
1019   }
1020
1021   QString aName (getNewObjectName());
1022   RETURN_WITH_MSG  ( !aName.trimmed().isEmpty(), tr( "EMPTY_NAME" ) )
1023
1024   RETURN_WITH_MSG  ( myIdList->count(), tr( "EMPTY_LIST" ) )
1025   return true;
1026 }
1027
1028 //=================================================================================
1029 // function : execute
1030 // purpose  :
1031 //=================================================================================
1032 bool GroupGUI_GroupDlg::execute( ObjectList& objects )
1033 {
1034   setInPlaceObj( GEOM::GEOM_Object::_nil() );
1035
1036   GEOM::GEOM_IGroupOperations_var anOp = GEOM::GEOM_IGroupOperations::_narrow(getOperation());
1037
1038   GEOM::GEOM_Object_var aGroup;
1039   if (myMode == CreateGroup)
1040     aGroup = anOp->CreateGroup(myMainObj, getShapeType());
1041   else if (myMode == EditGroup)
1042     aGroup = myGroup;
1043
1044   if (CORBA::is_nil(aGroup) || (myMode == CreateGroup && !anOp->IsDone()))
1045     return false;
1046
1047   GEOM::ListOfLong_var aCurrList = anOp->GetObjects(aGroup);
1048   if (!anOp->IsDone())
1049     return false;
1050
1051   if (aCurrList->length() > 0)
1052   {
1053     anOp->DifferenceIDs(aGroup, aCurrList);
1054     if (!anOp->IsDone())
1055       return false;
1056   }
1057
1058   int ii, nn = myIdList->count();
1059   if (nn > 0)
1060   {
1061     GEOM::ListOfLong_var aNewList = new GEOM::ListOfLong;
1062     aNewList->length(nn);
1063     for (ii = 0; ii < nn; ii++) {
1064       aNewList[ii] = myIdList->item(ii)->text().toInt();
1065     }
1066     anOp->UnionIDs(aGroup, aNewList);
1067     if (!anOp->IsDone())
1068       return false;
1069   }
1070
1071   SalomeApp_Study* study = getStudy();
1072   if ( study ) {
1073     char* objIOR = GEOMBase::GetIORFromObject( aGroup );
1074     std::string IOR( objIOR );
1075     free( objIOR );
1076     if ( IOR != "" ) {
1077       _PTR(SObject) SO ( study->studyDS()->FindObjectIOR( IOR ) );
1078       if ( SO ) {
1079         _PTR(StudyBuilder) aBuilder (study->studyDS()->NewBuilder());
1080         aBuilder->SetName( SO, getNewObjectName().toLatin1().constData() );
1081       }
1082     }
1083   }
1084
1085   objects.push_back( aGroup._retn() );
1086
1087   return true;
1088 }
1089
1090 //================================================================
1091 // Function : getFather
1092 // Purpose  : Get father object for object to be added in study
1093 //            ( called with addInStudy method )
1094 //================================================================
1095 GEOM::GEOM_Object_ptr GroupGUI_GroupDlg::getFather( GEOM::GEOM_Object_ptr theObj )
1096 {
1097   GEOM::GEOM_Object_var aFatherObj;
1098   if ( theObj->GetType() == GEOM_GROUP ) {
1099     GEOM::GEOM_IGroupOperations_var anOp = GEOM::GEOM_IGroupOperations::_narrow( getOperation() );
1100     aFatherObj = anOp->GetMainShape( theObj );
1101   }
1102   return aFatherObj._retn();
1103 }