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