Salome HOME
109ad04968c3e63369a47262f1c677a643f9472e
[modules/geom.git] / src / TransformationGUI / TransformationGUI_PositionDlg.cxx
1 // Copyright (C) 2007-2023  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, or (at your option) any later version.
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 // GEOM GEOMGUI : GUI for Geometry component
24 // File   : TransformationGUI_PositionDlg.cxx
25 // Author : Damien COQUERET, Open CASCADE S.A.S.
26 //
27 #include "TransformationGUI_PositionDlg.h"
28
29 #include <DlgRef.h>
30 #include <GeometryGUI.h>
31 #include <GEOMBase.h>
32
33 #include <SUIT_Session.h>
34 #include <SUIT_ResourceMgr.h>
35 #include <SalomeApp_Application.h>
36 #include <LightApp_SelectionMgr.h>
37 #include <TColStd_IndexedMapOfInteger.hxx>
38
39 // OCCT Includes
40 #include <TColStd_MapOfInteger.hxx>
41
42 #include <GEOMImpl_Types.hxx>
43
44 //=================================================================================
45 // class    : TransformationGUI_PositionDlg()
46 // purpose  : Constructs a TransformationGUI_PositionDlg which is a child of 'parent', with the
47 //            name 'name' and widget flags set to 'f'.
48 //            The dialog will by default be modeless, unless you set 'modal' to
49 //            TRUE to construct a modal dialog.
50 //=================================================================================
51 TransformationGUI_PositionDlg::TransformationGUI_PositionDlg
52 (GeometryGUI* theGeometryGUI, QWidget* parent, bool modal, Qt::WindowFlags fl)
53   : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl),
54     myInitial(true)
55 {
56   SUIT_ResourceMgr* aResMgr = myGeomGUI->getApp()->resourceMgr();
57   QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_POSITION")));
58   QPixmap image1 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_POSITION2")));
59   QPixmap image2 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_POSITION3")));
60   QPixmap imageselect (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT")));
61
62   setWindowTitle(tr("GEOM_POSITION_TITLE"));
63
64   /***************************************************************/
65   mainFrame()->GroupConstructors->setTitle(tr("GEOM_POSITION"));
66   mainFrame()->RadioButton1->setIcon(image0);
67   mainFrame()->RadioButton2->setIcon(image1);
68   mainFrame()->RadioButton3->setIcon(image2);
69
70   Group1 = new DlgRef_4Sel1Spin3Check(centralWidget());
71   Group1->GroupBox1->setTitle(tr("GEOM_ARGUMENTS"));
72   Group1->TextLabel1->setText(tr("GEOM_OBJECTS"));
73   Group1->TextLabel2->setText(tr("GEOM_START_LCS"));
74   Group1->TextLabel3->setText(tr("GEOM_DISTANCE"));
75   Group1->TextLabel4->setText(tr("GEOM_END_LCS"));
76   Group1->TextLabel5->setText(tr("GEOM_PATH_OBJECT"));
77   Group1->PushButton1->setIcon(imageselect);
78   Group1->PushButton2->setIcon(imageselect);
79   Group1->PushButton4->setIcon(imageselect);
80   Group1->PushButton5->setIcon(imageselect);
81   Group1->CheckButton1->setText(tr("GEOM_CREATE_COPY"));
82   Group1->CheckButton2->setText(tr("SELECT_UNPUBLISHED_EDGES"));
83   Group1->CheckButton3->setText(tr("GEOM_REVERSE_DIRECTION"));
84
85   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
86   layout->setMargin(0); layout->setSpacing(6);
87   layout->addWidget(Group1);
88   /***************************************************************/
89
90   setHelpFileName("modify_location_operation_page.html");
91
92   // Activate Create a Copy mode
93   Group1->CheckButton1->setChecked(true);
94   CreateCopyModeChanged();
95
96   Init();
97 }
98
99 //=================================================================================
100 // function : ~TransformationGUI_PositionDlg()
101 // purpose  : Destroys the object and frees any allocated resources
102 //=================================================================================
103 TransformationGUI_PositionDlg::~TransformationGUI_PositionDlg()
104 {
105   // no need to delete child widgets, Qt does it all for us
106 }
107
108 //=================================================================================
109 // function : Init()
110 // purpose  :
111 //=================================================================================
112 void TransformationGUI_PositionDlg::Init()
113 {
114   // init variables
115   Group1->LineEdit1->setReadOnly(true);
116   Group1->LineEdit2->setReadOnly(true);
117   Group1->LineEdit4->setReadOnly(true);
118   Group1->LineEdit5->setReadOnly(true);
119
120   Group1->LineEdit1->setText("");
121   Group1->LineEdit2->setText("");
122   Group1->LineEdit4->setText("");
123   Group1->LineEdit5->setText("");
124
125   initSpinBox(Group1->SpinBox_DX, 0, 1, 0.05, "parametric_precision" );
126   Group1->SpinBox_DX->setValue(0);
127
128   Group1->CheckButton2->setEnabled(false);
129
130   myObjects.clear();
131   myStartLCS.nullify();
132   myEndLCS.nullify();
133   myPath.nullify();
134
135   mainFrame()->GroupBoxPublish->show();
136
137   // signals and slots connections
138   connect(buttonOk(),    SIGNAL(clicked()), this, SLOT(ClickOnOk()));
139   connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
140
141   connect(this, SIGNAL(constructorsClicked(int)), this, SLOT(ConstructorsClicked(int)));
142
143   connect(Group1->PushButton1, SIGNAL(clicked()),       this, SLOT(SetEditCurrentArgument()));
144   connect(Group1->PushButton2, SIGNAL(clicked()),       this, SLOT(SetEditCurrentArgument()));
145   connect(Group1->PushButton4, SIGNAL(clicked()),       this, SLOT(SetEditCurrentArgument()));
146   connect(Group1->PushButton5, SIGNAL(clicked()),       this, SLOT(SetEditCurrentArgument()));
147
148   connect(Group1->CheckButton1,   SIGNAL(toggled(bool)), this, SLOT(CreateCopyModeChanged()));
149   connect(Group1->SpinBox_DX, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox()));
150
151   connect(Group1->CheckButton2,   SIGNAL(toggled(bool)), this, SLOT(SelectionTypeButtonClicked()));
152   connect(Group1->CheckButton3,   SIGNAL(toggled(bool)), this, SLOT(ValueChangedInSpinBox()));
153
154   initName(tr("GEOM_POSITION"));
155
156   ConstructorsClicked(0);
157 }
158
159 //=================================================================================
160 // function : ConstructorsClicked()
161 // purpose  : Radio button management
162 //=================================================================================
163 void TransformationGUI_PositionDlg::ConstructorsClicked (int constructorId)
164 {
165   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
166
167   Group1->LineEdit2->clear();
168   Group1->LineEdit4->clear();
169   Group1->LineEdit5->clear();
170   myStartLCS.nullify();
171   myEndLCS.nullify();
172   myPath.nullify();
173
174   switch (constructorId) {
175   case 0:
176     {
177       Group1->LineEdit2->hide();
178       Group1->TextLabel2->hide();
179       Group1->PushButton2->hide();
180
181       Group1->LineEdit5->hide();
182       Group1->TextLabel5->hide();
183       Group1->PushButton5->hide();
184
185       Group1->SpinBox_DX->hide();
186       Group1->TextLabel3->hide();
187
188       Group1->LineEdit4->show();
189       Group1->TextLabel4->show();
190       Group1->PushButton4->show();
191
192       Group1->PushButton1->click();
193
194       Group1->CheckButton2->hide();
195       Group1->CheckButton3->hide();
196     }
197     break;
198   case 1:
199     {
200       Group1->LineEdit2->show();
201       Group1->TextLabel2->show();
202       Group1->PushButton2->show();
203
204       Group1->LineEdit5->hide();
205       Group1->TextLabel5->hide();
206       Group1->PushButton5->hide();
207
208       Group1->SpinBox_DX->hide();
209       Group1->TextLabel3->hide();
210
211       Group1->PushButton1->click();
212
213       Group1->CheckButton2->hide();
214       Group1->CheckButton3->hide();
215     }
216     break;
217   case 2:
218     {
219       Group1->LineEdit4->hide();
220       Group1->TextLabel4->hide();
221       Group1->PushButton4->hide();
222
223       Group1->LineEdit2->hide();
224       Group1->TextLabel2->hide();
225       Group1->PushButton2->hide();
226
227       Group1->LineEdit5->show();
228       Group1->TextLabel5->show();
229       Group1->PushButton5->show();
230
231       Group1->SpinBox_DX->show();
232       Group1->TextLabel3->show();
233
234       Group1->PushButton1->click();
235
236       Group1->CheckButton2->show();
237       Group1->CheckButton3->show();
238     }
239     break;
240   }
241
242   qApp->processEvents();
243   updateGeometry();
244   resize(minimumSizeHint());
245
246   if (myInitial) {
247     myInitial = false;
248     SelectionIntoArgument();
249   }
250   else {
251     processPreview();
252   }
253 }
254
255 //=================================================================================
256 // function : SelectionBittonClicked()
257 // purpose  : Selection type Radio button management
258 //=================================================================================
259 void TransformationGUI_PositionDlg::SelectionTypeButtonClicked()
260 {
261   if ( Group1->CheckButton2->isChecked() ) {
262     localSelection( TopAbs_EDGE );
263   } else {
264     TColStd_MapOfInteger aMap;
265     aMap.Add(GEOM_WIRE);
266     aMap.Add(GEOM_LINE);
267     globalSelection(aMap);
268   }
269 }
270
271 //=================================================================================
272 // function : ValueChangedInSpinBox()
273 // purpose  :
274 //=================================================================================
275 void TransformationGUI_PositionDlg::ValueChangedInSpinBox()
276 {
277   processPreview();
278 }
279
280 //=================================================================================
281 // function : ClickOnOk()
282 // purpose  :
283 //=================================================================================
284 void TransformationGUI_PositionDlg::ClickOnOk()
285 {
286   setIsApplyAndClose( true );
287   if (ClickOnApply())
288     ClickOnCancel();
289 }
290
291 //=================================================================================
292 // function : ClickOnApply()
293 // purpose  :
294 //=================================================================================
295 bool TransformationGUI_PositionDlg::ClickOnApply()
296 {
297   if (!onAccept(Group1->CheckButton1->isChecked()))
298     return false;
299
300   initName();
301
302   // activate selection and connect selection manager
303   ConstructorsClicked(getConstructorId());
304   SelectionIntoArgument();
305
306   return true;
307 }
308
309 //=================================================================================
310 // function : SelectionIntoArgument()
311 // purpose  : Called when selection is changed or on dialog initialization or activation
312 //=================================================================================
313 void TransformationGUI_PositionDlg::SelectionIntoArgument()
314 {
315   erasePreview();
316   myEditCurrentArgument->setText("");
317
318   if ( myEditCurrentArgument == Group1->LineEdit1 ) {
319     myObjects = getSelected( TopAbs_SHAPE, -1 );
320     if ( !myObjects.isEmpty() ) {
321       QString aName = myObjects.count() > 1 ? QString( "%1_objects").arg( myObjects.count() ) : GEOMBase::GetName( myObjects[0].get() );
322       myEditCurrentArgument->setText( aName );
323     }
324   }
325   else if ( myEditCurrentArgument == Group1->LineEdit5 ) {
326     QList<TopAbs_ShapeEnum> types;
327     types << TopAbs_EDGE << TopAbs_WIRE;
328     GEOM::GeomObjPtr aSelectedObject = getSelected( types );
329     TopoDS_Shape aShape;
330     if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aShape ) && !aShape.IsNull() ) {
331       QString aName = GEOMBase::GetName( aSelectedObject.get() );
332       myEditCurrentArgument->setText( aName );
333       myPath = aSelectedObject;
334       if ( myObjects.isEmpty() )
335         Group1->PushButton1->click();
336     }
337     else {
338       myPath.nullify();
339     }
340   }
341   else {
342     GEOM::GeomObjPtr aSelectedObject = getSelected( TopAbs_SHAPE );
343     TopoDS_Shape aShape;
344     if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aShape ) && !aShape.IsNull() ) {
345       QString aName = GEOMBase::GetName( aSelectedObject.get() );
346       myEditCurrentArgument->setText( aName );
347       if ( myEditCurrentArgument == Group1->LineEdit2 ) {
348         myStartLCS = aSelectedObject;
349         if ( !myEndLCS )
350           Group1->PushButton4->click();
351         else if ( myObjects.isEmpty() )
352           Group1->PushButton1->click();
353       }
354       else if ( myEditCurrentArgument == Group1->LineEdit4 ) {
355         myEndLCS = aSelectedObject;
356         if ( myObjects.isEmpty() )
357           Group1->PushButton1->click();
358         else if ( getConstructorId() == 1 && !myStartLCS )
359           Group1->PushButton2->click();
360       }
361     }
362     else {
363       if ( myEditCurrentArgument == Group1->LineEdit2 )
364         myStartLCS.nullify();
365       else if ( myEditCurrentArgument == Group1->LineEdit4 )
366         myEndLCS.nullify();
367     }
368   }
369
370   processPreview();
371 }
372
373 //=================================================================================
374 // function : SetEditCurrentArgument()
375 // purpose  :
376 //=================================================================================
377 void TransformationGUI_PositionDlg::SetEditCurrentArgument()
378 {
379   QPushButton* send = (QPushButton*)sender();
380
381   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
382   if (send == Group1->PushButton1) {
383     myEditCurrentArgument = Group1->LineEdit1;
384
385     globalSelection();
386
387     Group1->PushButton2->setDown(false);
388     Group1->PushButton4->setDown(false);
389     Group1->PushButton5->setDown(false);
390     Group1->LineEdit2->setEnabled(false);
391     Group1->LineEdit4->setEnabled(false);
392     Group1->LineEdit5->setEnabled(false);
393
394     Group1->CheckButton2->setEnabled(false);
395   }
396   else if (send == Group1->PushButton2) {
397     myEditCurrentArgument = Group1->LineEdit2;
398
399     TColStd_MapOfInteger aMap;
400     aMap.Add(GEOM_PLANE);
401     aMap.Add(GEOM_MARKER);
402     globalSelection(aMap);
403
404     Group1->PushButton1->setDown(false);
405     Group1->PushButton4->setDown(false);
406     Group1->PushButton5->setDown(false);
407     Group1->LineEdit1->setEnabled(false);
408     Group1->LineEdit4->setEnabled(false);
409     Group1->LineEdit5->setEnabled(false);
410
411     Group1->CheckButton2->setEnabled(false);
412   }
413   else if (send == Group1->PushButton4) {
414     myEditCurrentArgument = Group1->LineEdit4;
415
416     TColStd_MapOfInteger aMap;
417     aMap.Add(GEOM_PLANE);
418     aMap.Add(GEOM_MARKER);
419     globalSelection(aMap);
420
421     Group1->PushButton1->setDown(false);
422     Group1->PushButton2->setDown(false);
423     Group1->PushButton5->setDown(false);
424     Group1->LineEdit1->setEnabled(false);
425     Group1->LineEdit2->setEnabled(false);
426     Group1->LineEdit5->setEnabled(false);
427
428     Group1->CheckButton2->setEnabled(false);
429   }
430   else if (send == Group1->PushButton5) {
431     myEditCurrentArgument = Group1->LineEdit5;
432
433     Group1->CheckButton2->setEnabled(true);
434
435     if ( Group1->CheckButton2->isChecked() ) {
436       localSelection( TopAbs_EDGE );
437     } else {
438       TColStd_MapOfInteger aMap;
439       aMap.Add(GEOM_WIRE);
440       aMap.Add(GEOM_LINE);
441       globalSelection(aMap);
442     }
443
444     Group1->PushButton1->setDown(false);
445     Group1->PushButton2->setDown(false);
446     Group1->PushButton4->setDown(false);
447     Group1->LineEdit1->setEnabled(false);
448     Group1->LineEdit2->setEnabled(false);
449     Group1->LineEdit4->setEnabled(false);
450   }
451   connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
452           this, SLOT(SelectionIntoArgument()));
453
454   // enable line edit
455   myEditCurrentArgument->setEnabled(true);
456   myEditCurrentArgument->setFocus();
457   // after setFocus(), because it will be setDown(false) when loses focus
458   send->setDown(true);
459
460   // seems we need it only to avoid preview disappearing, caused by selection mode change
461   processPreview();
462 }
463
464 //=================================================================================
465 // function : ActivateThisDialog()
466 // purpose  :
467 //=================================================================================
468 void TransformationGUI_PositionDlg::ActivateThisDialog()
469 {
470   GEOMBase_Skeleton::ActivateThisDialog();
471   connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ),
472            this, SLOT( SelectionIntoArgument() ) );
473
474   connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ),
475            this, SLOT( SelectionIntoArgument() ) );
476
477   ConstructorsClicked( getConstructorId() );
478 }
479
480 //=================================================================================
481 // function : enterEvent()
482 // purpose  : when mouse enter onto the QWidget
483 //=================================================================================
484 void TransformationGUI_PositionDlg::enterEvent (QEvent*)
485 {
486   if (!mainFrame()->GroupConstructors->isEnabled())
487     ActivateThisDialog();
488 }
489
490 //=================================================================================
491 // function : createOperation
492 // purpose  :
493 //=================================================================================
494 GEOM::GEOM_IOperations_ptr TransformationGUI_PositionDlg::createOperation()
495 {
496   return getGeomEngine()->GetITransformOperations();
497 }
498
499 //=================================================================================
500 // function : isValid
501 // purpose  :
502 //=================================================================================
503 bool TransformationGUI_PositionDlg::isValid (QString& /*msg*/)
504 {
505   bool ok = false;
506   switch (getConstructorId()) {
507   case 0:
508     ok = !myObjects.isEmpty() && myEndLCS;
509     break;
510   case 1:
511     ok = !myObjects.isEmpty() && myStartLCS && myEndLCS;
512     break;
513   case 2:
514     ok = !myObjects.isEmpty() && myPath;
515     break;
516   default:
517     break;
518   }
519   return ok;
520 }
521
522 //=================================================================================
523 // function : execute
524 // purpose  :
525 //=================================================================================
526 bool TransformationGUI_PositionDlg::execute (ObjectList& objects)
527 {
528   bool res = false;
529   bool toCreateCopy = IsPreview() || Group1->CheckButton1->isChecked();
530   GEOM::GEOM_Object_var anObj;
531
532   GEOM::GEOM_ITransformOperations_var anOper = GEOM::GEOM_ITransformOperations::_narrow(getOperation());
533
534   switch (getConstructorId()) {
535   case 0:
536     {
537       for (int i = 0; i < myObjects.count(); i++) {
538         anObj = toCreateCopy ? 
539           anOper->PositionShapeCopy(myObjects[i].get(), myObjects[i].get(), myEndLCS.get()) :
540           anOper->PositionShape(myObjects[i].get(), myObjects[i].get(), myEndLCS.get());
541
542         if (!anObj->_is_nil())
543           objects.push_back(anObj._retn());
544       }
545       res = true;
546       break;
547     }
548   case 1:
549     {
550       for (int i = 0; i < myObjects.count(); i++) {
551           anObj = toCreateCopy ? 
552             anOper->PositionShapeCopy(myObjects[i].get(), myStartLCS.get(), myEndLCS.get()) :
553             anOper->PositionShape(myObjects[i].get(), myStartLCS.get(), myEndLCS.get());
554         if (!anObj->_is_nil())
555           objects.push_back(anObj._retn());
556       }
557       res = true;
558       break;
559     }
560   case 2:
561     {
562       double aDistance = Group1->SpinBox_DX->value();
563       bool toReverse = Group1->CheckButton3->isChecked();
564       for (int i = 0; i < myObjects.count(); i++) {
565         anObj = anOper->PositionAlongPath(myObjects[i].get(), myPath.get(), aDistance, toCreateCopy, toReverse);
566         if (!anObj->_is_nil())
567           objects.push_back(anObj._retn());
568       }
569       res = true;
570       break;
571     }
572   }
573
574   return res;
575 }
576
577 //=================================================================================
578 // function : restoreSubShapes
579 // purpose  :
580 //=================================================================================
581 void TransformationGUI_PositionDlg::restoreSubShapes (SALOMEDS::SObject_ptr theSObject)
582 {
583   if (mainFrame()->CheckBoxRestoreSS->isChecked()) {
584     // empty list of arguments means that all arguments should be restored
585     getGeomEngine()->RestoreSubShapesSO(theSObject, GEOM::ListOfGO(),
586                                         /*theFindMethod=*/GEOM::FSM_Transformed,
587                                         /*theInheritFirstArg=*/true,
588                                         mainFrame()->CheckBoxAddPrefix->isChecked());
589   }
590 }
591
592 //=================================================================================
593 // function :  CreateCopyModeChanged()
594 // purpose  :
595 //=================================================================================
596 void TransformationGUI_PositionDlg::CreateCopyModeChanged()
597 {
598   mainFrame()->GroupBoxName->setEnabled(Group1->CheckButton1->isChecked());
599 }
600
601 //=================================================================================
602 // function : addSubshapeToStudy
603 // purpose  : virtual method to add new SubObjects if local selection
604 //=================================================================================
605 void TransformationGUI_PositionDlg::addSubshapesToStudy()
606 {
607   if ( getConstructorId() == 2 )
608     GEOMBase::PublishSubObject( myPath.get() );
609 }
610
611 //=================================================================================
612 // function : getSourceObjects
613 // purpose  : virtual method to get source objects
614 //=================================================================================
615 QList<GEOM::GeomObjPtr> TransformationGUI_PositionDlg::getSourceObjects()
616 {
617   QList<GEOM::GeomObjPtr> res;
618   if ( Group1->CheckButton1->isChecked() ) {
619     res.append(myObjects);
620     res << myStartLCS << myEndLCS << myPath;
621   }
622   return res;
623 }