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