Salome HOME
0021179: EDF 1654 SMESH GEOM: better look'n'feel
[modules/geom.git] / src / TransformationGUI / TransformationGUI_MultiRotationDlg.cxx
1 // Copyright (C) 2007-2011  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 //  File   : TransformationGUI_MultiRotationDlg.cxx
23 //  Author : Damien COQUERET, Open CASCADE S.A.S.
24
25 #include "TransformationGUI_MultiRotationDlg.h"
26
27 #include <DlgRef.h>
28 #include <GeometryGUI.h>
29 #include <GEOMBase.h>
30
31 #include <SUIT_Session.h>
32 #include <SUIT_ResourceMgr.h>
33 #include <SalomeApp_Application.h>
34 #include <LightApp_SelectionMgr.h>
35
36 // OCCT Includes
37 #include <TopoDS_Shape.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS.hxx>
40 #include <TopExp.hxx>
41 #include <TColStd_IndexedMapOfInteger.hxx>
42 #include <TopTools_IndexedMapOfShape.hxx>
43
44 #include <GEOMImpl_Types.hxx>
45
46 //=================================================================================
47 // class    : TransformationGUI_MultiRotationDlg()
48 // purpose  : Constructs a TransformationGUI_MultiRotationDlg which is a child of 'parent', with the
49 //            name 'name' and widget flags set to 'f'.
50 //            The dialog will by default be modeless, unless you set 'modal' to
51 //            TRUE to construct a modal dialog.
52 //=================================================================================
53 TransformationGUI_MultiRotationDlg::TransformationGUI_MultiRotationDlg
54 (GeometryGUI* theGeometryGUI, QWidget* parent, bool modal, Qt::WindowFlags fl)
55   : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl),
56     myInitial(true)
57 {
58   SUIT_ResourceMgr* aResMgr = myGeomGUI->getApp()->resourceMgr();
59   QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_MULTIROTATION_SIMPLE")));
60   QPixmap image1 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_MULTIROTATION_DOUBLE")));
61   QPixmap image2 (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT")));
62
63   setWindowTitle(tr("GEOM_MULTIROTATION_TITLE"));
64
65   /***************************************************************/
66   mainFrame()->GroupConstructors->setTitle(tr("GEOM_MULTIROTATION"));
67   mainFrame()->RadioButton1->setIcon(image0);
68   mainFrame()->RadioButton2->setIcon(image1);
69   mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
70   mainFrame()->RadioButton3->close();
71
72   GroupPoints = new DlgRef_2Sel1SpinInt(centralWidget());
73   GroupPoints->GroupBox1->setTitle(tr("GEOM_MULTIROTATION_SIMPLE"));
74   GroupPoints->TextLabel1->setText(tr("GEOM_MAIN_OBJECT"));
75   GroupPoints->TextLabel2->setText(tr("GEOM_VECTOR"));
76   GroupPoints->TextLabel3->setText(tr("GEOM_NB_TIMES"));
77   GroupPoints->PushButton1->setIcon(image2);
78   GroupPoints->PushButton2->setIcon(image2);
79   GroupPoints->LineEdit1->setReadOnly(true);
80   GroupPoints->LineEdit2->setReadOnly(true);
81
82   GroupDimensions = new DlgRef_2Sel4Spin1Check(centralWidget());
83   GroupDimensions->GroupBox1->setTitle(tr("GEOM_MULTIROTATION_DOUBLE"));
84   GroupDimensions->TextLabel1->setText(tr("GEOM_MAIN_OBJECT"));
85   GroupDimensions->TextLabel2->setText(tr("GEOM_VECTOR"));
86   GroupDimensions->TextLabel3->setText(tr("GEOM_ANGLE"));
87   GroupDimensions->TextLabel4->setText(tr("GEOM_NB_TIMES"));
88   GroupDimensions->TextLabel5->setText(tr("GEOM_STEP"));
89   GroupDimensions->TextLabel6->setText(tr("GEOM_NB_TIMES"));
90   GroupDimensions->CheckButton1->setText(tr("GEOM_REVERSE"));
91   GroupDimensions->PushButton1->setIcon(image2);
92   GroupDimensions->PushButton2->setIcon(image2);
93   GroupDimensions->LineEdit1->setReadOnly(true);
94   GroupDimensions->LineEdit2->setReadOnly(true);
95
96   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
97   layout->setMargin(0); layout->setSpacing(6);
98   layout->addWidget(GroupPoints);
99   layout->addWidget(GroupDimensions);
100   /***************************************************************/
101
102   setHelpFileName("multi_rotation_operation_page.html");
103
104   Init();
105 }
106
107 //=================================================================================
108 // function : ~TransformationGUI_MultiRotationDlg()
109 // purpose  : Destroys the object and frees any allocated resources
110 //=================================================================================
111 TransformationGUI_MultiRotationDlg::~TransformationGUI_MultiRotationDlg()
112 {
113   // no need to delete child widgets, Qt does it all for us
114 }
115
116 //=================================================================================
117 // function : Init()
118 // purpose  :
119 //=================================================================================
120 void TransformationGUI_MultiRotationDlg::Init()
121 {
122   // Get setting of step value from file configuration
123   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
124   double step = resMgr->doubleValue("Geometry", "SettingsGeomStep", 100);
125
126   int SpecificStep1 = 5;
127   int SpecificStep2 = 1;
128   // init variables
129   myAng = 45.0;
130   myStep = 50.0;
131   myNbTimes1 = myNbTimes2 = 2;
132
133   // min, max, step and decimals for spin boxes & initial values
134   initSpinBox(GroupPoints->SpinBox_DX, 1, 999, SpecificStep2);
135   GroupPoints->SpinBox_DX->setValue(myNbTimes1);
136
137   initSpinBox(GroupDimensions->SpinBox_DX1, COORD_MIN, COORD_MAX, SpecificStep1, "angle_precision" );
138   initSpinBox(GroupDimensions->SpinBox_DY1, 1, 999, SpecificStep2);
139   initSpinBox(GroupDimensions->SpinBox_DX2, COORD_MIN, COORD_MAX, step,"length_precision" );
140   initSpinBox(GroupDimensions->SpinBox_DY2, 1, 999, SpecificStep2);
141   GroupDimensions->SpinBox_DX1->setValue(myAng);
142   GroupDimensions->SpinBox_DY1->setValue(myNbTimes1);
143   GroupDimensions->SpinBox_DX2->setValue(myStep);
144   GroupDimensions->SpinBox_DY2->setValue(myNbTimes2);
145
146   GroupPoints->LineEdit1->setText("");
147   GroupPoints->LineEdit2->setText("");
148
149   GroupDimensions->LineEdit1->setText("");
150   GroupDimensions->LineEdit2->setText("");
151
152   myBase.nullify();
153   myVector.nullify();
154
155   mainFrame()->GroupBoxPublish->show();
156
157   // signals and slots connections
158   connect(buttonOk(),    SIGNAL(clicked()), this, SLOT(ClickOnOk()));
159   connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
160
161   connect(this,          SIGNAL(constructorsClicked(int)), this, SLOT(ConstructorsClicked(int)));
162
163   connect(GroupPoints->PushButton1,     SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
164   connect(GroupPoints->PushButton2,     SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
165   connect(GroupDimensions->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
166   connect(GroupDimensions->PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
167
168   connect(GroupPoints->SpinBox_DX,      SIGNAL(valueChanged(int)),    this, SLOT(ValueChangedInSpinBox(int)));
169   connect(GroupDimensions->SpinBox_DX1, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
170   connect(GroupDimensions->SpinBox_DY1, SIGNAL(valueChanged(int)),    this, SLOT(ValueChangedInSpinBox(int)));
171   connect(GroupDimensions->SpinBox_DX2, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
172   connect(GroupDimensions->SpinBox_DY2, SIGNAL(valueChanged(int)),    this, SLOT(ValueChangedInSpinBox(int)));
173
174   connect(GroupDimensions->SpinBox_DX1,SIGNAL(textChanged( const QString& )),
175           this, SLOT(TextValueChangedInSpinBox( const QString& )));
176
177   connect(myGeomGUI, SIGNAL(SignalDefaultStepValueChanged(double)), this, SLOT(SetDoubleSpinBoxStep(double)));
178
179   connect(GroupDimensions->CheckButton1, SIGNAL(toggled(bool)), this, SLOT(ReverseAngle()));
180
181   initName(tr("GEOM_MULTIROTATION"));
182
183   ConstructorsClicked(0);
184 }
185
186 //=================================================================================
187 // function : SetDoubleSpinBoxStep()
188 // purpose  : Double spin box management
189 //=================================================================================
190 void TransformationGUI_MultiRotationDlg::SetDoubleSpinBoxStep (double step)
191 {
192   GroupDimensions->SpinBox_DX2->setSingleStep(step);
193
194   // san: Commented so as not to override specific step settings
195   //GroupPoints->SpinBox_DX->setSingleStep((int)step);
196   //GroupDimensions->SpinBox_DX1->setSingleStep(step);
197   //GroupDimensions->SpinBox_DY1->setSingleStep((int)step);
198   //GroupDimensions->SpinBox_DY2->setSingleStep((int)step);
199 }
200
201 //=================================================================================
202 // function : ConstructorsClicked()
203 // purpose  : Radio button management
204 //=================================================================================
205 void TransformationGUI_MultiRotationDlg::ConstructorsClicked (int constructorId)
206 {
207   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
208
209   switch (constructorId) {
210   case 0: // Rotate simple
211     {
212       GroupDimensions->hide();
213       GroupPoints->show();
214
215       GroupPoints->LineEdit1->setText("");
216       GroupPoints->LineEdit2->setText("");
217       myBase.nullify();
218       myVector.nullify();
219
220       GroupPoints->SpinBox_DX->setValue(myNbTimes1);
221
222       GroupPoints->PushButton1->click();
223     }
224     break;
225   case 1: // Rotate double
226     {
227       GroupPoints->hide();
228       GroupDimensions->show();
229
230       GroupDimensions->LineEdit1->setText("");
231       GroupDimensions->LineEdit2->setText("");
232       myBase.nullify();
233       myVector.nullify();
234
235       GroupDimensions->SpinBox_DX1->setValue(myAng);
236       GroupDimensions->SpinBox_DY1->setValue(myNbTimes1);
237       GroupDimensions->SpinBox_DX2->setValue(myStep);
238       GroupDimensions->SpinBox_DY2->setValue(myNbTimes2);
239
240       GroupDimensions->PushButton1->click();
241     }
242     break;
243   }
244
245   qApp->processEvents();
246   updateGeometry();
247   resize(minimumSizeHint());
248
249   if (myInitial) {
250     myInitial = false;
251     SelectionIntoArgument();
252   }
253   else {
254     processPreview();
255   }
256 }
257
258 //=================================================================================
259 // function : ClickOnOk()
260 // purpose  :
261 //=================================================================================
262 void TransformationGUI_MultiRotationDlg::ClickOnOk()
263 {
264   setIsApplyAndClose( true );
265   if (ClickOnApply())
266     ClickOnCancel();
267 }
268
269 //=================================================================================
270 // function : ClickOnApply()
271 // purpose  :
272 //=================================================================================
273 bool TransformationGUI_MultiRotationDlg::ClickOnApply()
274 {
275   if (!onAccept())
276     return false;
277
278   initName();
279   // activate selection and connect selection manager
280   ConstructorsClicked(getConstructorId());
281   return true;
282 }
283
284 //=================================================================================
285 // function : SelectionIntoArgument()
286 // purpose  : Called when selection is changed or on dialog initialization or activation
287 //=================================================================================
288 void TransformationGUI_MultiRotationDlg::SelectionIntoArgument()
289 {
290   erasePreview();
291
292   TopAbs_ShapeEnum aNeedType = ( myEditCurrentArgument == GroupPoints->LineEdit2 ||
293                                  myEditCurrentArgument == GroupDimensions->LineEdit2 ) ?
294     TopAbs_EDGE : TopAbs_SHAPE;
295   GEOM::GeomObjPtr aSelectedObject = getSelected( aNeedType );
296   TopoDS_Shape aShape;
297   if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aShape ) && !aShape.IsNull() ) {
298     QString aName = GEOMBase::GetName( aSelectedObject.get() );
299     myEditCurrentArgument->setText( aName );
300     if ( myEditCurrentArgument == GroupPoints->LineEdit1 ) {
301       myBase = aSelectedObject;
302       if ( !myVector )
303         GroupPoints->PushButton2->click();
304     }
305     else if ( myEditCurrentArgument == GroupPoints->LineEdit2)  {
306       myVector = aSelectedObject;
307       if ( !myBase )
308         GroupPoints->PushButton1->click();
309     }
310     else if ( myEditCurrentArgument == GroupDimensions->LineEdit1 ) {
311       myBase = aSelectedObject;
312       if ( !myVector )
313         GroupDimensions->PushButton2->click();
314     }
315     else if ( myEditCurrentArgument == GroupDimensions->LineEdit2 ) {
316       myVector = aSelectedObject;
317       if ( !myBase )
318         GroupDimensions->PushButton1->click();
319     }
320     
321     // clear selection
322     disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
323     myGeomGUI->getApp()->selectionMgr()->clearSelected();
324     connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
325             this, SLOT(SelectionIntoArgument()));
326   }
327   else {
328     if ( myEditCurrentArgument == GroupPoints->LineEdit1 ||
329          myEditCurrentArgument == GroupDimensions->LineEdit1 )
330       myBase.nullify();
331     else if ( myEditCurrentArgument == GroupPoints->LineEdit2 ||
332               myEditCurrentArgument == GroupDimensions->LineEdit2 )
333       myVector.nullify();
334     myEditCurrentArgument->setText("");
335   }
336
337   processPreview();
338 }
339
340 //=================================================================================
341 // function : SetEditCurrentArgument()
342 // purpose  :
343 //=================================================================================
344 void TransformationGUI_MultiRotationDlg::SetEditCurrentArgument()
345 {
346   QPushButton* send = (QPushButton*)sender();
347
348   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
349   globalSelection(GEOM_ALLSHAPES);
350
351   if (send == GroupPoints->PushButton1) {
352     myEditCurrentArgument = GroupPoints->LineEdit1;
353
354     GroupPoints->PushButton2->setDown(false);
355     GroupPoints->LineEdit2->setEnabled(false);
356   }
357   else if (send == GroupPoints->PushButton2) {
358     myEditCurrentArgument = GroupPoints->LineEdit2;
359
360     localSelection(GEOM::GEOM_Object::_nil(), TopAbs_EDGE);
361
362     GroupPoints->PushButton1->setDown(false);
363     GroupPoints->LineEdit1->setEnabled(false);
364   }
365   else if (send == GroupDimensions->PushButton1) {
366     myEditCurrentArgument = GroupDimensions->LineEdit1;
367
368     GroupDimensions->PushButton2->setDown(false);
369     GroupDimensions->LineEdit2->setEnabled(false);
370   }
371   else if (send == GroupDimensions->PushButton2) {
372     myEditCurrentArgument = GroupDimensions->LineEdit2;
373
374     localSelection(GEOM::GEOM_Object::_nil(), TopAbs_EDGE);
375
376     GroupDimensions->PushButton1->setDown(false);
377     GroupDimensions->LineEdit1->setEnabled(false);
378   }
379   connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
380           this, SLOT(SelectionIntoArgument()));
381
382   // enable line edit
383   myEditCurrentArgument->setEnabled(true);
384   myEditCurrentArgument->setFocus();
385   // after setFocus(), because it will be setDown(false) when loses focus
386   send->setDown(true);
387
388   // seems we need it only to avoid preview disappearing, caused by selection mode change
389   processPreview();
390 }
391
392 //=================================================================================
393 // function : ActivateThisDialog()
394 // purpose  :
395 //=================================================================================
396 void TransformationGUI_MultiRotationDlg::ActivateThisDialog()
397 {
398   GEOMBase_Skeleton::ActivateThisDialog();
399   connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ),
400            this, SLOT( SelectionIntoArgument() ) );
401
402   ConstructorsClicked( getConstructorId() );
403 }
404
405 //=================================================================================
406 // function : enterEvent()
407 // purpose  :
408 //=================================================================================
409 void TransformationGUI_MultiRotationDlg::enterEvent (QEvent*)
410 {
411   if (!mainFrame()->GroupConstructors->isEnabled())
412     ActivateThisDialog();
413 }
414
415 //=================================================================================
416 // function : TextValueChangedInSpinBox()
417 // purpose  :
418 //=================================================================================
419 void TransformationGUI_MultiRotationDlg::TextValueChangedInSpinBox(const QString& s){
420   bool isDigit;
421   s.toDouble(&isDigit);
422   if(!isDigit)
423     GroupDimensions->CheckButton1->setChecked(false);
424   GroupDimensions->CheckButton1->setEnabled(isDigit);
425 }
426
427 //=================================================================================
428 // function : ValueChangedInSpinBox()
429 // purpose  :
430 //=================================================================================
431 void TransformationGUI_MultiRotationDlg::ValueChangedInSpinBox (double newValue)
432 {
433   QObject* send = (QObject*)sender();
434
435   if (send == GroupDimensions->SpinBox_DX1)
436     myAng = newValue;
437   else if (send == GroupDimensions->SpinBox_DX2)
438     myStep = newValue;
439
440   processPreview();
441 }
442
443 //=================================================================================
444 // function : ValueChangedInSpinBox()
445 // purpose  :
446 //=================================================================================
447 void TransformationGUI_MultiRotationDlg::ValueChangedInSpinBox (int newValue)
448 {
449   QObject* send = (QObject*)sender();
450
451   if (send == GroupPoints->SpinBox_DX || send == GroupDimensions->SpinBox_DY1)
452     myNbTimes1 = newValue;
453   else if (send == GroupDimensions->SpinBox_DY2)
454     myNbTimes2 = newValue;
455
456   processPreview();
457 }
458
459 //=================================================================================
460 // function : ReverseAngle()
461 // purpose  : 'state' not used here
462 //=================================================================================
463 void TransformationGUI_MultiRotationDlg::ReverseAngle()
464 {
465   myAng = -myAng;
466
467   int aConstructorId = getConstructorId();
468
469   if (aConstructorId == 1)
470     GroupDimensions->SpinBox_DX1->setValue(myAng);
471
472   processPreview();
473 }
474
475 //=================================================================================
476 // function : createOperation
477 // purpose  :
478 //=================================================================================
479 GEOM::GEOM_IOperations_ptr TransformationGUI_MultiRotationDlg::createOperation()
480 {
481   return getGeomEngine()->GetITransformOperations(getStudyId());
482 }
483
484 //=================================================================================
485 // function : isValid
486 // purpose  :
487 //=================================================================================
488 bool TransformationGUI_MultiRotationDlg::isValid (QString& msg)
489 {
490   bool ok = false;
491   switch(getConstructorId()){
492   case 0:
493     ok = GroupPoints->SpinBox_DX->isValid( msg, !IsPreview() ) &&  myBase && myVector;
494     break;
495   case 1:
496     ok = GroupDimensions->SpinBox_DX1->isValid( msg, !IsPreview() ) &&
497          GroupDimensions->SpinBox_DY1->isValid( msg, !IsPreview() ) &&
498          GroupDimensions->SpinBox_DX2->isValid( msg, !IsPreview() ) &&
499          GroupDimensions->SpinBox_DY2->isValid( msg, !IsPreview() ) &&
500          myBase && myVector;
501     break;
502   default:
503     break;
504   }
505   return ok;
506 }
507
508 //=================================================================================
509 // function : execute
510 // purpose  :
511 //=================================================================================
512 bool TransformationGUI_MultiRotationDlg::execute (ObjectList& objects)
513 {
514   bool res = false;
515
516   GEOM::GEOM_Object_var anObj;
517   QStringList aParameters;
518
519   GEOM::GEOM_ITransformOperations_var anOper = GEOM::GEOM_ITransformOperations::_narrow(getOperation());
520
521   switch (getConstructorId()) {
522   case 0:
523     if ( myBase && myVector ) {
524       anObj = anOper->MultiRotate1D(myBase.get(), myVector.get(), myNbTimes1);
525       if(!IsPreview())
526         aParameters<<GroupPoints->SpinBox_DX->text();
527       res = true;
528     }
529     break;
530   case 1:
531     if ( myBase && myVector ) {
532       anObj = anOper->MultiRotate2D(myBase.get(), myVector.get(), myAng, myNbTimes1, myStep, myNbTimes2);
533       if(!IsPreview()) {
534         aParameters<<GroupDimensions->SpinBox_DX1->text();
535         aParameters<<GroupDimensions->SpinBox_DY1->text();
536         aParameters<<GroupDimensions->SpinBox_DX2->text();
537         aParameters<<GroupDimensions->SpinBox_DY2->text();
538       }
539       res = true;
540     }
541     break;
542   }
543
544   if (!anObj->_is_nil()) {
545     if(!IsPreview())
546       anObj->SetParameters(aParameters.join(":").toLatin1().constData());
547     objects.push_back(anObj._retn());
548   }
549
550   return res;
551 }
552
553 //=================================================================================
554 // function : addSubshapeToStudy
555 // purpose  : virtual method to add new SubObjects if local selection
556 //=================================================================================
557 void TransformationGUI_MultiRotationDlg::addSubshapesToStudy()
558 {
559   switch (getConstructorId()) {
560   case 0:
561   case 1:
562     GEOMBase::PublishSubObject( myVector.get() );
563     break;
564   default:
565     break;
566   }
567 }
568
569 //=================================================================================
570 // function : restoreSubShapes
571 // purpose  :
572 //=================================================================================
573 void TransformationGUI_MultiRotationDlg::restoreSubShapes (SALOMEDS::Study_ptr   theStudy,
574                                                            SALOMEDS::SObject_ptr theSObject)
575 {
576   if (mainFrame()->CheckBoxRestoreSS->isChecked()) {
577     // we pass here the first operation argument (object) through the list of arguments
578     // because the rotation operation place its arguments in the data structure in another order,
579     // and we need to point the first argument directly
580     GEOM::ListOfGO_var anArgs = new GEOM::ListOfGO;
581     anArgs->length(1);
582     anArgs[0] = myBase.copy();
583     getGeomEngine()->RestoreSubShapesSO(theStudy, theSObject, anArgs,
584                                         /*theFindMethod=*/GEOM::FSM_MultiTransformed,
585                                         /*theInheritFirstArg=*/true,
586                                         mainFrame()->CheckBoxAddPrefix->isChecked());
587   }
588 }