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