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