Salome HOME
Merge from V5_1_3_BR branch (07/12/09)
[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 anOper = GEOM::GEOM_IGroupOperations::_narrow( getOperation() );
198         myMainObj = anOper->GetMainShape( myGroup );
199         if ( !CORBA::is_nil( myMainObj ) )
200           myMainName->setText( GEOMBase::GetName( myMainObj ) );
201
202         setShapeType( (TopAbs_ShapeEnum)anOper->GetType( myGroup ) );
203
204         GEOM::ListOfLong_var aCurrList = anOper->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 ) || !myIsShapeType )
614     return;
615
616   GEOM::ListOfLong_var aSubShapes;
617
618   //   if ( !myPlaceCheckBox->isChecked() )
619   if ( subSelectionWay() == ALL_SUBSHAPES )
620     {
621       if ( !myIsShapeType )
622         return;
623       myIdList->clear();
624       GEOM::GEOM_IShapesOperations_var aShOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
625       aSubShapes = aShOp->SubShapeAllIDs(myMainObj, getShapeType(), false);
626       
627       if ( !aShOp->IsDone() )
628         return;
629     }
630   else
631     {
632       aSubShapes = new GEOM::ListOfLong();
633       aSubShapes->length( myMain2InPlaceIndices.Extent() );
634       TColStd_DataMapIteratorOfDataMapOfIntegerInteger m2ip( myMain2InPlaceIndices );
635       for ( int i = 0; m2ip.More(); i++, m2ip.Next() )
636         aSubShapes[ i ] = m2ip.Key();
637     }
638   bool isBlocked = myIdList->signalsBlocked();
639   myIdList->blockSignals( true );
640   
641   for ( int i = 0, n = aSubShapes->length(); i < n; i++ ) {
642     CORBA::Long anIndex = aSubShapes[i];
643     if ( anIndex < 0 )
644       continue;
645     
646     QListWidgetItem* anItem = 0;
647     QString text = QString( "%1" ).arg( anIndex );
648     if ( !myInPlaceObj->_is_nil() ) {
649       QList<QListWidgetItem*> found = myIdList->findItems( text, Qt::MatchExactly );
650       if ( found.count() ) anItem = found[0];
651     }
652     if ( !anItem ) {
653       anItem = new QListWidgetItem( text );
654       myIdList->addItem( anItem );
655     }
656     anItem->setSelected( true );
657   }
658   
659   myIdList->blockSignals( isBlocked );
660   highlightSubShapes();
661 }
662
663 //=================================================================================
664 // function : add
665 // purpose  : 
666 //=================================================================================
667 void GroupGUI_GroupDlg::add()
668 {
669   TColStd_MapOfInteger aMap;
670   for ( int i = 0, n = myIdList->count(); i < n; i++ )
671     aMap.Add( myIdList->item( i )->text().toInt() );
672
673   TColStd_IndexedMapOfInteger aMapIndex;
674
675   SALOME_ListIO aSelIOs;
676   SalomeApp_Application* app = myGeomGUI->getApp();
677   if ( app ) {
678     LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
679     if ( aSelMgr ) {
680       LightApp_SelectionMgr::MapEntryOfMapOfInteger aMap;
681       aSelMgr->selectedSubOwners( aMap );
682       if ( aMap.Size() == 1 )
683         aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value();
684       else { // selected the same subshape as the main object
685         SALOME_ListIO aSelList;
686         TColStd_IndexedMapOfInteger aMap;
687         aSelMgr->selectedObjects(aSelList);
688         if (aSelList.Extent() == 1) {
689           Standard_Boolean aRes = Standard_False;
690           GEOM::GEOM_Object_var aSelectedObject = GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aRes);
691           if ( aSelectedObject->_is_equivalent(myMainObj) )
692             aMapIndex.Add(1); // add index of the only subshape of selected type
693         }
694       }
695     }
696   }
697   GEOM::ListOfGO anObjects;
698   // get selected sub-shapes of myInPlaceObj
699   if ( aMapIndex.Extent() > 0 && !myInPlaceObj->_is_nil() )
700   {
701     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
702
703     anObjects.length( aMapIndex.Extent() );
704     for ( int i = 1; i <= aMapIndex.Extent(); i++ )
705       anObjects[ i-1 ] = aShapesOp->GetSubShape( myInPlaceObj, aMapIndex( i ));
706
707     aMapIndex.Clear();
708   }
709
710   // try to find out and process the object browser selection or InPlace sub-shapes
711   if ( !aMapIndex.Extent() )
712   {
713     if ( anObjects.length() == 0 )
714       GEOMBase::ConvertListOfIOInListOfGO(aSelIOs, anObjects);
715
716     GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
717     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
718
719     for (int i = 0; i < anObjects.length(); i++)
720     {
721       GEOM::GEOM_Object_var aGeomObj = anObjects[i];
722       GEOM::ListOfGO_var aSubObjects  = new GEOM::ListOfGO();
723       TopoDS_Shape aShape;
724       if ( GEOMBase::GetShape(aGeomObj, aShape, getShapeType()) )
725       {
726         aSubObjects->length(1);
727         aSubObjects[0] = aGeomObj;
728       }
729       else if (aGeomObj->GetType() == GEOM_GROUP)
730         aSubObjects = aShapesOp->MakeExplode( aGeomObj, getShapeType(), false);
731       else
732         break;
733
734       for (int i = 0; i < aSubObjects->length(); i++)
735       {
736         TopoDS_Shape aShape;
737         if ( GEOMBase::GetShape(aSubObjects[i], aShape, getShapeType()) )
738         {
739           CORBA::Long anIndex;
740             anIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
741           if ( anIndex >= 0 )
742             aMapIndex.Add( anIndex );
743         }
744       }
745     }
746   }
747
748   if ( aMapIndex.Extent() >= 1 ) {
749     bool isBlocked = myIdList->signalsBlocked();
750     myIdList->blockSignals( true );
751
752     for ( int i = 1, n = aMapIndex.Extent(); i <= n; i++ ) {
753       if ( aMap.Contains( aMapIndex( i ) ) )
754         continue;
755
756       QListWidgetItem* anItem = new QListWidgetItem( QString( "%1" ).arg( aMapIndex( i ) ) );
757       myIdList->addItem( anItem );
758       anItem->setSelected( true );
759     }
760
761     myIdList->blockSignals( isBlocked );
762   }
763
764   updateState();
765 }
766
767 //=================================================================================
768 // function : remove
769 // purpose  : 
770 //=================================================================================
771 void GroupGUI_GroupDlg::remove()
772 {
773   bool isBlocked = myIdList->signalsBlocked();
774   myIdList->blockSignals( true );
775
776   QListIterator<QListWidgetItem*> it( myIdList->selectedItems() );
777   while ( it.hasNext() )
778     delete it.next();
779
780   myIdList->blockSignals( isBlocked );
781
782   highlightSubShapes();
783 }
784
785 //=======================================================================
786 //function : subSelectionWay
787 //purpose  : 
788 //=======================================================================
789
790 int GroupGUI_GroupDlg::subSelectionWay() const
791 {
792   return mySelectionWayGroup->checkedId();
793 }
794
795 //=================================================================================
796 // function : getShapeType()
797 // purpose  :
798 //=================================================================================
799 TopAbs_ShapeEnum GroupGUI_GroupDlg::getShapeType() const
800 {
801   switch ( getConstructorId() ) {
802   case 0:  return TopAbs_VERTEX;
803   case 1:  return TopAbs_EDGE;
804   case 2:  return TopAbs_FACE;
805   case 3:  return TopAbs_SOLID;
806   default: return TopAbs_SHAPE;
807   }
808 }
809
810 //=================================================================================
811 // function : setShapeType()
812 // purpose  :
813 //=================================================================================
814 void GroupGUI_GroupDlg::setShapeType( const TopAbs_ShapeEnum theType )
815 {
816   int anId = 0;
817   switch ( theType ) {
818   case TopAbs_VERTEX: anId = 0; break;
819   case TopAbs_EDGE:   anId = 1; break;
820   case TopAbs_FACE:   anId = 2; break;
821   case TopAbs_SOLID:  anId = 3; break;
822   }
823   setConstructorId( anId );
824   if (!myIsShapeType)
825   {
826     myIsShapeType = true;
827     // workaround top avoid set checked button 0
828     setConstructorId( anId );
829   }
830 }
831
832
833 //=================================================================================
834 // function : activateSelection
835 // purpose  : Activate selection in accordance with myEditCurrentArgument
836 //=================================================================================
837 void GroupGUI_GroupDlg::activateSelection()
838 {
839   globalSelection( GEOM_ALLSHAPES );
840
841   // local selection
842   if ( !myMainObj->_is_nil() && !myEditCurrentArgument/* && mySelSubBtn->isChecked()*/
843        && myIsShapeType) { // check if shape type is already choosen by user
844   
845 //     if ( !myPlaceCheckBox->isChecked() )
846     if ( subSelectionWay() == ALL_SUBSHAPES )
847       localSelection( myMainObj, getShapeType() );
848     else if ( !myInPlaceObj->_is_nil() )
849       localSelection( myInPlaceObj, getShapeType() );
850   }
851
852   SelectionIntoArgument();
853 }
854
855 //=================================================================================
856 // function : updateState
857 // purpose  : 
858 //=================================================================================
859 void GroupGUI_GroupDlg::updateState()
860 {
861   bool isAdd = false;
862
863   TColStd_IndexedMapOfInteger aMapIndex;
864
865   SALOME_ListIO aSelIOs;
866   SalomeApp_Application* app = myGeomGUI->getApp();
867   if ( app ) {
868     LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
869     if ( aSelMgr ) {
870       LightApp_SelectionMgr::MapEntryOfMapOfInteger aMap;
871       aSelMgr->selectedSubOwners( aMap );
872       if ( aMap.Size() == 1 )
873         aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value();
874       else { // selected the same subshape as the main object
875         SALOME_ListIO aSelList;
876         aSelMgr->selectedObjects(aSelList);
877         if (aSelList.Extent() == 1) {
878           myBusy = true;
879           Standard_Boolean aRes = Standard_False;
880           GEOM::GEOM_Object_var aSelectedObject = GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aRes);
881           if ( aSelectedObject->_is_equivalent(myMainObj) ) {
882             aMapIndex.Add(1); // add index of the only subshape of selected type
883             TColStd_MapOfInteger anIds; // higlight selected index
884             anIds.Add(1);
885             aSelMgr->AddOrRemoveIndex(aSelList.First(), anIds, false);
886           }
887           myBusy = false;
888         }
889       }
890     }
891   }
892
893   // try to find out and process the object browser selection
894   if ( !aMapIndex.Extent() && !CORBA::is_nil( myMainObj ) ) {
895     GEOM::ListOfGO anObjects;
896     //GEOMBase::ConvertListOfIOInListOfGO(selectedIO(), anObjects);
897     GEOMBase::ConvertListOfIOInListOfGO(aSelIOs, anObjects);
898
899     GEOM::GEOM_ILocalOperations_var aLocOp = getGeomEngine()->GetILocalOperations( getStudyId() );
900     GEOM::GEOM_IShapesOperations_var aShapesOp = getGeomEngine()->GetIShapesOperations( getStudyId() );
901
902     isAdd = true;
903
904     for (int i = 0; i < anObjects.length(); i++)
905     {
906       GEOM::GEOM_Object_var aGeomObj = anObjects[i];
907       GEOM::ListOfGO_var aSubObjects = new GEOM::ListOfGO();
908       TopoDS_Shape aShape;
909       if ( GEOMBase::GetShape(aGeomObj, aShape, getShapeType()) ) {
910         aSubObjects->length(1);
911         aSubObjects[0] = aGeomObj;
912       }
913       else if (aGeomObj->GetType() == GEOM_GROUP) {
914         aSubObjects = aShapesOp->MakeExplode( aGeomObj, getShapeType(), false);
915       }
916       else {
917         aMapIndex.Clear();
918         break;
919       }
920
921       for (int i = 0; i < aSubObjects->length(); i++)
922       {
923         TopoDS_Shape aShape;
924         aSubObjects[i];
925         if ( GEOMBase::GetShape(aSubObjects[i], aShape, getShapeType()) )
926         {
927           CORBA::Long anIndex;
928           anIndex = aLocOp->GetSubShapeIndex( myMainObj, aSubObjects[i] );
929           if ( anIndex >= 0 )
930             aMapIndex.Add( anIndex );
931           else
932             isAdd = false;
933         }
934         else
935           isAdd = false;
936
937         if ( !isAdd ) {
938           aMapIndex.Clear();
939           break;
940         }
941       }
942       if ( !isAdd ) {
943         aMapIndex.Clear();
944         break;
945       }
946     }
947   }
948
949   isAdd = aMapIndex.Extent() > 0;
950
951   myAddBtn->setEnabled( !myEditCurrentArgument && !CORBA::is_nil( myMainObj ) && isAdd );
952   bool hasSel = myIdList->selectedItems().count() > 0;
953   myRemBtn->setEnabled( hasSel );
954   //mySelSubBtn->setEnabled( !CORBA::is_nil( myMainObj ) );
955   //myPlaceCheckBox->setEnabled( !CORBA::is_nil( myMainObj ) );
956   mySelectionWayGroupBox->setEnabled( !CORBA::is_nil( myMainObj ) );
957   mySelAllBtn->setEnabled( !CORBA::is_nil( myMainObj ) );
958 //   mySelBtn2->setEnabled( myPlaceCheckBox->isChecked() );
959 //   myShape2Name->setEnabled( myPlaceCheckBox->isChecked() );
960   mySelBtn2->setEnabled(    subSelectionWay() != ALL_SUBSHAPES );
961   myShape2Name->setEnabled( subSelectionWay() != ALL_SUBSHAPES );
962 //   if ( !myPlaceCheckBox->isChecked() )
963   if ( subSelectionWay() == ALL_SUBSHAPES )
964     setInPlaceObj( GEOM::GEOM_Object::_nil() );
965 }
966
967 //=================================================================================
968 // function : selectionChanged
969 // purpose  :
970 //=================================================================================
971 void GroupGUI_GroupDlg::selectionChanged()
972 {
973   highlightSubShapes();
974 }
975
976 //=================================================================================
977 // function : highlightSubShapes
978 // purpose  :
979 //=================================================================================
980 void GroupGUI_GroupDlg::highlightSubShapes()
981 {
982   if ( CORBA::is_nil( myMainObj ) )
983     return;
984
985   Standard_Boolean isOk;
986   char* objIOR;
987
988   if ( myInPlaceObj->_is_nil() )
989     objIOR = GEOMBase::GetIORFromObject( myMainObj );
990   else
991     objIOR = GEOMBase::GetIORFromObject( myInPlaceObj );
992
993   Handle(GEOM_AISShape) aSh = GEOMBase::ConvertIORinGEOMAISShape( objIOR, isOk, true );
994   free( objIOR );
995   if ( !isOk || aSh.IsNull() )
996     return;
997
998   TColStd_MapOfInteger anIds;
999
1000   myBusy = true;
1001
1002   int ii = 0, nn = myIdList->count();
1003   for ( ; ii < nn; ii++ )
1004   {
1005     if ( myIdList->item( ii )->isSelected() ) {
1006       int id = myIdList->item( ii )->text().toInt();
1007       //       if ( myPlaceCheckBox->isChecked() )
1008       if ( subSelectionWay() != ALL_SUBSHAPES )
1009       {
1010         if ( myMain2InPlaceIndices.IsBound( id ) )
1011           id = myMain2InPlaceIndices( id );
1012         else {
1013           myIdList->item( ii )->setSelected( false );
1014           continue;
1015         }
1016       }
1017       anIds.Add( id );
1018     }
1019   }
1020   SalomeApp_Application* app = myGeomGUI->getApp();
1021   LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
1022   aSelMgr->clearSelected();
1023
1024   aSelMgr->AddOrRemoveIndex(aSh->getIO(), anIds, false);
1025
1026   myBusy = false;
1027
1028   if (nn < 3000)
1029     updateState();
1030   else {
1031     myAddBtn->setEnabled( true );
1032     myRemBtn->setEnabled( true );
1033   }
1034 }
1035
1036 //=================================================================================
1037 // function : createOperation
1038 // purpose  :
1039 //=================================================================================
1040 GEOM::GEOM_IOperations_ptr GroupGUI_GroupDlg::createOperation()
1041 {
1042   return getGeomEngine()->GetIGroupOperations( getStudyId() );
1043 }
1044
1045 #define RETURN_WITH_MSG(a, b) \
1046   if ( !(a) ) { \
1047     theMessage += (b); \
1048     return false; \
1049   }
1050
1051 //=================================================================================
1052 // function : isValid()
1053 // purpose  : Verify validity of input data
1054 //=================================================================================
1055 bool GroupGUI_GroupDlg::isValid( QString& theMessage )
1056 {
1057   SalomeApp_Study* study = getStudy();
1058   ASSERT(study);
1059   RETURN_WITH_MSG  ( !study->studyDS()->GetProperties()->IsLocked(), tr( "GEOM_STUDY_LOCKED" ) )
1060
1061   if ( myMode == CreateGroup ) {
1062     RETURN_WITH_MSG( !CORBA::is_nil( myMainObj ), tr( "NO_MAIN_OBJ" ) )
1063   }
1064   else {
1065     RETURN_WITH_MSG( !CORBA::is_nil( myMainObj ), tr( "NO_GROUP" ) )
1066   }
1067
1068   QString aName (getNewObjectName());
1069   RETURN_WITH_MSG  ( !aName.trimmed().isEmpty(), tr( "EMPTY_NAME" ) )
1070
1071   RETURN_WITH_MSG  ( myIdList->count(), tr( "EMPTY_LIST" ) )
1072   return true;
1073 }
1074
1075 //=================================================================================
1076 // function : execute
1077 // purpose  :
1078 //=================================================================================
1079 bool GroupGUI_GroupDlg::execute( ObjectList& objects )
1080 {
1081   setInPlaceObj( GEOM::GEOM_Object::_nil() );
1082
1083   GEOM::GEOM_IGroupOperations_var anOper = GEOM::GEOM_IGroupOperations::_narrow(getOperation());
1084
1085   GEOM::GEOM_Object_var aGroup;
1086   if (myMode == CreateGroup)
1087     aGroup = anOper->CreateGroup(myMainObj, getShapeType());
1088   else if (myMode == EditGroup)
1089     aGroup = myGroup;
1090
1091   if (CORBA::is_nil(aGroup) || (myMode == CreateGroup && !anOper->IsDone()))
1092     return false;
1093
1094   GEOM::ListOfLong_var aCurrList = anOper->GetObjects(aGroup);
1095   if (!anOper->IsDone())
1096     return false;
1097
1098   if (aCurrList->length() > 0)
1099   {
1100     anOper->DifferenceIDs(aGroup, aCurrList);
1101     if (!anOper->IsDone())
1102       return false;
1103   }
1104
1105   int ii, nn = myIdList->count();
1106   if (nn > 0)
1107   {
1108     GEOM::ListOfLong_var aNewList = new GEOM::ListOfLong;
1109     aNewList->length(nn);
1110     for (ii = 0; ii < nn; ii++) {
1111       aNewList[ii] = myIdList->item(ii)->text().toInt();
1112     }
1113     anOper->UnionIDs(aGroup, aNewList);
1114     if (!anOper->IsDone())
1115       return false;
1116   }
1117
1118   SalomeApp_Study* study = getStudy();
1119   if ( study ) {
1120     char* objIOR = GEOMBase::GetIORFromObject( aGroup );
1121     std::string IOR( objIOR );
1122     free( objIOR );
1123     if ( IOR != "" ) {
1124       _PTR(SObject) SO ( study->studyDS()->FindObjectIOR( IOR ) );
1125       if ( SO ) {
1126         _PTR(StudyBuilder) aBuilder (study->studyDS()->NewBuilder());
1127         aBuilder->SetName( SO, getNewObjectName().toLatin1().constData() );
1128       }
1129     }
1130   }
1131
1132   objects.push_back( aGroup._retn() );
1133
1134   return true;
1135 }
1136
1137 //================================================================
1138 // Function : getFather
1139 // Purpose  : Get father object for object to be added in study
1140 //            ( called with addInStudy method )
1141 //================================================================
1142 GEOM::GEOM_Object_ptr GroupGUI_GroupDlg::getFather( GEOM::GEOM_Object_ptr theObj )
1143 {
1144   GEOM::GEOM_Object_var aFatherObj;
1145   if ( theObj->GetType() == GEOM_GROUP ) {
1146     GEOM::GEOM_IGroupOperations_var anOper = GEOM::GEOM_IGroupOperations::_narrow( getOperation() );
1147     aFatherObj = anOper->GetMainShape( theObj );
1148   }
1149   return aFatherObj._retn();
1150 }