Salome HOME
Fix hang-up when displaying sphere in OCC viewer
[modules/geom.git] / src / TransformationGUI / TransformationGUI_PositionDlg.cxx
1 //  Copyright (C) 2007-2010  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
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     displayPreview();
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( GEOM::GEOM_Object::_nil(), 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   displayPreview();
278 }
279
280 //=================================================================================
281 // function : ClickOnOk()
282 // purpose  :
283 //=================================================================================
284 void TransformationGUI_PositionDlg::ClickOnOk()
285 {
286   if (ClickOnApply())
287     ClickOnCancel();
288 }
289
290 //=================================================================================
291 // function : ClickOnApply()
292 // purpose  :
293 //=================================================================================
294 bool TransformationGUI_PositionDlg::ClickOnApply()
295 {
296   if (!onAccept(Group1->CheckButton1->isChecked()))
297     return false;
298
299   initName();
300
301   myObjects.clear();
302   myEditCurrentArgument = Group1->LineEdit1;
303   myEditCurrentArgument->setText("");
304   myGeomGUI->getApp()->selectionMgr()->clearSelected();
305
306   // activate selection and connect selection manager
307   ConstructorsClicked(getConstructorId());
308   return true;
309 }
310
311 //=================================================================================
312 // function : SelectionIntoArgument()
313 // purpose  : Called when selection is changed or on dialog initialization or activation
314 //=================================================================================
315 void TransformationGUI_PositionDlg::SelectionIntoArgument()
316 {
317   erasePreview();
318   myEditCurrentArgument->setText("");
319
320   if ( myEditCurrentArgument == Group1->LineEdit1 ) {
321     myObjects = getSelected( TopAbs_SHAPE, -1 );
322     if ( !myObjects.isEmpty() ) {
323       QString aName = myObjects.count() > 1 ? QString( "%1_objects").arg( myObjects.count() ) : GEOMBase::GetName( myObjects[0].get() );
324       myEditCurrentArgument->setText( aName );
325     }
326   }
327   else if ( myEditCurrentArgument == Group1->LineEdit5 ) {
328     QList<TopAbs_ShapeEnum> types;
329     types << TopAbs_EDGE << TopAbs_WIRE;
330     GEOM::GeomObjPtr aSelectedObject = getSelected( types );
331     TopoDS_Shape aShape;
332     if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aShape ) && !aShape.IsNull() ) {
333       QString aName = GEOMBase::GetName( aSelectedObject.get() );
334       myEditCurrentArgument->setText( aName );
335       myPath = aSelectedObject;
336       if ( myObjects.isEmpty() )
337         Group1->PushButton1->click();
338     }
339     else {
340       myPath.nullify();
341     }
342   }
343   else {
344     GEOM::GeomObjPtr aSelectedObject = getSelected( TopAbs_SHAPE );
345     TopoDS_Shape aShape;
346     if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aShape ) && !aShape.IsNull() ) {
347       QString aName = GEOMBase::GetName( aSelectedObject.get() );
348       myEditCurrentArgument->setText( aName );
349       if ( myEditCurrentArgument == Group1->LineEdit2 ) {
350         myStartLCS = aSelectedObject;
351         if ( !myEndLCS )
352           Group1->PushButton4->click();
353         else if ( myObjects.isEmpty() )
354           Group1->PushButton1->click();
355       }
356       else if ( myEditCurrentArgument == Group1->LineEdit4 ) {
357         myEndLCS = aSelectedObject;
358         if ( myObjects.isEmpty() )
359           Group1->PushButton1->click();
360         else if ( getConstructorId() == 1 && !myStartLCS )
361           Group1->PushButton2->click();
362       }
363     }
364     else {
365       if ( myEditCurrentArgument == Group1->LineEdit2 )
366         myStartLCS.nullify();
367       else if ( myEditCurrentArgument == Group1->LineEdit4 )
368         myEndLCS.nullify();
369     }
370   }
371
372   displayPreview();
373 }
374
375 //=================================================================================
376 // function : SetEditCurrentArgument()
377 // purpose  :
378 //=================================================================================
379 void TransformationGUI_PositionDlg::SetEditCurrentArgument()
380 {
381   QPushButton* send = (QPushButton*)sender();
382
383   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
384   if (send == Group1->PushButton1) {
385     myEditCurrentArgument = Group1->LineEdit1;
386
387     globalSelection();
388
389     Group1->PushButton2->setDown(false);
390     Group1->PushButton4->setDown(false);
391     Group1->PushButton5->setDown(false);
392     Group1->LineEdit2->setEnabled(false);
393     Group1->LineEdit4->setEnabled(false);
394     Group1->LineEdit5->setEnabled(false);
395
396     Group1->CheckButton2->setEnabled(false);
397   }
398   else if (send == Group1->PushButton2) {
399     myEditCurrentArgument = Group1->LineEdit2;
400
401     TColStd_MapOfInteger aMap;
402     aMap.Add(GEOM_PLANE);
403     aMap.Add(GEOM_MARKER);
404     globalSelection(aMap);
405
406     Group1->PushButton1->setDown(false);
407     Group1->PushButton4->setDown(false);
408     Group1->PushButton5->setDown(false);
409     Group1->LineEdit1->setEnabled(false);
410     Group1->LineEdit4->setEnabled(false);
411     Group1->LineEdit5->setEnabled(false);
412
413     Group1->CheckButton2->setEnabled(false);
414   }
415   else if (send == Group1->PushButton4) {
416     myEditCurrentArgument = Group1->LineEdit4;
417
418     TColStd_MapOfInteger aMap;
419     aMap.Add(GEOM_PLANE);
420     aMap.Add(GEOM_MARKER);
421     globalSelection(aMap);
422
423     Group1->PushButton1->setDown(false);
424     Group1->PushButton2->setDown(false);
425     Group1->PushButton5->setDown(false);
426     Group1->LineEdit1->setEnabled(false);
427     Group1->LineEdit2->setEnabled(false);
428     Group1->LineEdit5->setEnabled(false);
429
430     Group1->CheckButton2->setEnabled(false);
431   }
432   else if (send == Group1->PushButton5) {
433     myEditCurrentArgument = Group1->LineEdit5;
434
435     Group1->CheckButton2->setEnabled(true);
436
437     if ( Group1->CheckButton2->isChecked() ) {
438       localSelection( GEOM::GEOM_Object::_nil(), TopAbs_EDGE );
439     } else {
440       TColStd_MapOfInteger aMap;
441       aMap.Add(GEOM_WIRE);
442       aMap.Add(GEOM_LINE);
443       globalSelection(aMap);
444     }
445
446     Group1->PushButton1->setDown(false);
447     Group1->PushButton2->setDown(false);
448     Group1->PushButton4->setDown(false);
449     Group1->LineEdit1->setEnabled(false);
450     Group1->LineEdit2->setEnabled(false);
451     Group1->LineEdit4->setEnabled(false);
452   }
453   connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
454           this, SLOT(SelectionIntoArgument()));
455
456   // enable line edit
457   myEditCurrentArgument->setEnabled(true);
458   myEditCurrentArgument->setFocus();
459   // after setFocus(), because it will be setDown(false) when loses focus
460   send->setDown(true);
461
462   // seems we need it only to avoid preview disappearing, caused by selection mode change
463   displayPreview();
464 }
465
466 //=================================================================================
467 // function : ActivateThisDialog()
468 // purpose  :
469 //=================================================================================
470 void TransformationGUI_PositionDlg::ActivateThisDialog()
471 {
472   GEOMBase_Skeleton::ActivateThisDialog();
473   connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ),
474            this, SLOT( SelectionIntoArgument() ) );
475
476   connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ),
477            this, SLOT( SelectionIntoArgument() ) );
478
479   ConstructorsClicked( getConstructorId() );
480 }
481
482 //=================================================================================
483 // function : enterEvent()
484 // purpose  : when mouse enter onto the QWidget
485 //=================================================================================
486 void TransformationGUI_PositionDlg::enterEvent (QEvent*)
487 {
488   if (!mainFrame()->GroupConstructors->isEnabled())
489     ActivateThisDialog();
490 }
491
492 //=================================================================================
493 // function : createOperation
494 // purpose  :
495 //=================================================================================
496 GEOM::GEOM_IOperations_ptr TransformationGUI_PositionDlg::createOperation()
497 {
498   return getGeomEngine()->GetITransformOperations(getStudyId());
499 }
500
501 //=================================================================================
502 // function : isValid
503 // purpose  :
504 //=================================================================================
505 bool TransformationGUI_PositionDlg::isValid (QString& /*msg*/)
506 {
507   bool ok = false;
508   switch (getConstructorId()) {
509   case 0:
510     ok = !myObjects.isEmpty() && myEndLCS;
511     break;
512   case 1:
513     ok = !myObjects.isEmpty() && myStartLCS && myEndLCS;
514     break;
515   case 2:
516     ok = !myObjects.isEmpty() && myPath;
517     break;
518   default:
519     break;
520   }
521   return ok;
522 }
523
524 //=================================================================================
525 // function : execute
526 // purpose  :
527 //=================================================================================
528 bool TransformationGUI_PositionDlg::execute (ObjectList& objects)
529 {
530   bool res = false;
531   bool toCreateCopy = IsPreview() || Group1->CheckButton1->isChecked();
532   GEOM::GEOM_Object_var anObj;
533
534   GEOM::GEOM_ITransformOperations_var anOper = GEOM::GEOM_ITransformOperations::_narrow(getOperation());
535
536   switch (getConstructorId()) {
537   case 0:
538     {
539       for (int i = 0; i < myObjects.count(); i++) {
540         anObj = toCreateCopy ? 
541           anOper->PositionShapeCopy(myObjects[i].get(), myObjects[i].get(), myEndLCS.get()) :
542           anOper->PositionShape(myObjects[i].get(), myObjects[i].get(), myEndLCS.get());
543
544         if (!anObj->_is_nil())
545           objects.push_back(anObj._retn());
546       }
547       res = true;
548       break;
549     }
550   case 1:
551     {
552       for (int i = 0; i < myObjects.count(); i++) {
553           anObj = toCreateCopy ? 
554             anOper->PositionShapeCopy(myObjects[i].get(), myStartLCS.get(), myEndLCS.get()) :
555             anOper->PositionShape(myObjects[i].get(), myStartLCS.get(), myEndLCS.get());
556         if (!anObj->_is_nil())
557           objects.push_back(anObj._retn());
558       }
559       res = true;
560       break;
561     }
562   case 2:
563     {
564       double aDistance = Group1->SpinBox_DX->value();
565       bool toReverse = Group1->CheckButton3->isChecked();
566       for (int i = 0; i < myObjects.count(); i++) {
567         anObj = anOper->PositionAlongPath(myObjects[i].get(), myPath.get(), aDistance, toCreateCopy, toReverse);
568         if (!anObj->_is_nil())
569           objects.push_back(anObj._retn());
570       }
571       res = true;
572       break;
573     }
574   }
575
576   return res;
577 }
578
579 //=================================================================================
580 // function : restoreSubShapes
581 // purpose  :
582 //=================================================================================
583 void TransformationGUI_PositionDlg::restoreSubShapes (SALOMEDS::Study_ptr   theStudy,
584                                                       SALOMEDS::SObject_ptr theSObject)
585 {
586   if (mainFrame()->CheckBoxRestoreSS->isChecked()) {
587     // empty list of arguments means that all arguments should be restored
588     getGeomEngine()->RestoreSubShapesSO(theStudy, theSObject, GEOM::ListOfGO(),
589                                         /*theFindMethod=*/GEOM::FSM_Transformed,
590                                         /*theInheritFirstArg=*/true,
591                                         mainFrame()->CheckBoxAddPrefix->isChecked());
592   }
593 }
594
595 //=================================================================================
596 // function :  CreateCopyModeChanged()
597 // purpose  :
598 //=================================================================================
599 void TransformationGUI_PositionDlg::CreateCopyModeChanged()
600 {
601   mainFrame()->GroupBoxName->setEnabled(Group1->CheckButton1->isChecked());
602 }
603
604 //=================================================================================
605 // function : addSubshapeToStudy
606 // purpose  : virtual method to add new SubObjects if local selection
607 //=================================================================================
608 void TransformationGUI_PositionDlg::addSubshapesToStudy()
609 {
610   if ( getConstructorId() == 2 )
611     GEOMBase::PublishSubObject( myPath.get() );
612 }