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