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