Salome HOME
Translation of Qt messages
[modules/shaper.git] / src / PartSet / PartSet_WidgetSketchLabel.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "PartSet_WidgetSketchLabel.h"
21 #include "PartSet_Tools.h"
22 #include "PartSet_Module.h"
23 #include "PartSet_PreviewPlanes.h"
24 #include "PartSet_SketcherReentrantMgr.h"
25
26 #include "SketchPlugin_SketchEntity.h"
27
28 #include <XGUI_ActionsMgr.h>
29 #include <XGUI_Displayer.h>
30 #include <XGUI_ModuleConnector.h>
31 #include <XGUI_SelectionActivate.h>
32 #include <XGUI_Selection.h>
33 #include <XGUI_SelectionMgr.h>
34 #include <XGUI_Tools.h>
35 #include <XGUI_ViewerProxy.h>
36 #include <XGUI_Workshop.h>
37
38 #include <ModelAPI_ResultBody.h>
39 #include <ModelAPI_Tools.h>
40
41 #include <ModuleBase_Operation.h>
42 #include <ModuleBase_ViewerPrs.h>
43 #include <ModuleBase_Tools.h>
44 #include <ModuleBase_IModule.h>
45 #include <ModuleBase_IPropertyPanel.h>
46
47 #include <GeomAlgoAPI_FaceBuilder.h>
48 #include <GeomAlgoAPI_ShapeTools.h>
49 #include <GeomDataAPI_Point.h>
50 #include <GeomDataAPI_Dir.h>
51 #include <GeomAPI_XYZ.h>
52 #include <GeomAPI_Face.h>
53 #include <GeomAPI_Edge.h>
54 #include <GeomAPI_ShapeExplorer.h>
55
56 #include <SketchPlugin_Sketch.h>
57 #include <SketcherPrs_Tools.h>
58
59 #include <Precision.hxx>
60 #include <gp_Pln.hxx>
61 #include <gp_Pnt.hxx>
62 #include <gp_Dir.hxx>
63 #include <AIS_Shape.hxx>
64 #include <AIS_DimensionSelectionMode.hxx>
65 #include <Bnd_Box.hxx>
66
67 #include <Config_WidgetAPI.h>
68 #include <Config_PropManager.h>
69
70 #include <QLabel>
71 #include <QApplication>
72 #include <QVBoxLayout>
73 #include <QHBoxLayout>
74 #include <QCheckBox>
75 #include <QGroupBox>
76 #include <QPushButton>
77 #include <QStackedWidget>
78 #include <QLineEdit>
79 #include <QDoubleValidator>
80
81 #ifndef DBL_MAX
82 #define DBL_MAX 1.7976931348623158e+308
83 #endif
84
85 PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
86                         ModuleBase_IWorkshop* theWorkshop,
87                         const Config_WidgetAPI* theData,
88                         const QMap<PartSet_Tools::ConstraintVisibleState, bool>& toShowConstraints)
89 : ModuleBase_WidgetValidated(theParent, theWorkshop, theData), myOpenTransaction(false),
90 myIsSelection(false)
91 {
92   QVBoxLayout* aLayout = new QVBoxLayout(this);
93   ModuleBase_Tools::zeroMargins(aLayout);
94
95   myStackWidget = new QStackedWidget(this);
96   myStackWidget->setContentsMargins(0,0,0,0);
97   aLayout->addWidget(myStackWidget);
98
99   // Define label for plane selection
100   QWidget* aFirstWgt = new QWidget(this);
101
102   // Size of the View control
103   mySizeOfViewWidget = new QWidget(aFirstWgt);
104   QHBoxLayout* aSizeLayout = new QHBoxLayout(mySizeOfViewWidget);
105   aSizeLayout->addWidget(new QLabel("Size of the view", mySizeOfViewWidget));
106   mySizeOfView = new QLineEdit(mySizeOfViewWidget);
107
108   QDoubleValidator* aValidator = new QDoubleValidator(0, DBL_MAX, 12, mySizeOfView);
109   aValidator->setLocale(ModuleBase_Tools::doubleLocale());
110   aValidator->setNotation(QDoubleValidator::StandardNotation);
111   mySizeOfView->setValidator(aValidator);
112   aSizeLayout->addWidget(mySizeOfView);
113
114   QString aText = translate(theData->getProperty("title"));
115   QLabel* aLabel = new QLabel(aText, aFirstWgt);
116   aLabel->setWordWrap(true);
117   QString aTooltip = translate(theData->getProperty("tooltip"));
118   aLabel->setToolTip(aTooltip);
119   aLabel->setIndent(5);
120
121   aLayout = new QVBoxLayout(aFirstWgt);
122   ModuleBase_Tools::zeroMargins(aLayout);
123   aLayout->addWidget(mySizeOfViewWidget);
124   aLayout->addWidget(aLabel);
125
126   myRemoveExternal = new QCheckBox(tr("Remove external dependencies"), aFirstWgt);
127   myRemoveExternal->setChecked(false);
128   aLayout->addWidget(myRemoveExternal);
129   myRemoveExternal->setVisible(false);
130
131   aLayout->addStretch(1);
132
133   myStackWidget->addWidget(aFirstWgt);
134
135   // Define widget for sketch manmagement
136   QWidget* aSecondWgt = new QWidget(this);
137   aLayout = new QVBoxLayout(aSecondWgt);
138   ModuleBase_Tools::zeroMargins(aLayout);
139
140   QGroupBox* aViewBox = new QGroupBox(tr("Sketcher plane"), this);
141   QVBoxLayout* aViewLayout = new QVBoxLayout(aViewBox);
142
143   myViewInverted = new QCheckBox(tr("Reversed"), aViewBox);
144   aViewLayout->addWidget(myViewInverted);
145
146   QPushButton* aSetViewBtn =
147     new QPushButton(QIcon(":icons/plane_view.png"), tr("Set plane view"), aViewBox);
148   connect(aSetViewBtn, SIGNAL(clicked(bool)), this, SLOT(onSetPlaneView()));
149   aViewLayout->addWidget(aSetViewBtn);
150
151   aLayout->addWidget(aViewBox);
152
153   QMap<PartSet_Tools::ConstraintVisibleState, QString> aStates;
154   aStates[PartSet_Tools::Geometrical] = tr("Show geometrical constraints");
155   aStates[PartSet_Tools::Dimensional] = tr("Show dimensional constraints");
156   aStates[PartSet_Tools::Expressions] = tr("Show existing expressions");
157
158   QMap<PartSet_Tools::ConstraintVisibleState, QString>::const_iterator anIt = aStates.begin(),
159                                                         aLast = aStates.end();
160   for (; anIt != aLast; anIt++) {
161     QCheckBox* aShowConstraints = new QCheckBox(anIt.value(), this);
162     connect(aShowConstraints, SIGNAL(toggled(bool)), this, SLOT(onShowConstraint(bool)));
163     aLayout->addWidget(aShowConstraints);
164
165     PartSet_Tools::ConstraintVisibleState aState = anIt.key();
166     myShowConstraints[aState] = aShowConstraints;
167
168     if (toShowConstraints.contains(aState))
169       aShowConstraints->setChecked(toShowConstraints[aState]);
170   }
171   myShowPoints = new QCheckBox(tr("Show free points"), this);
172   connect(myShowPoints, SIGNAL(toggled(bool)), this, SIGNAL(showFreePoints(bool)));
173   aLayout->addWidget(myShowPoints);
174
175   myAutoConstraints = new QCheckBox(tr("Automatic constraints"), this);
176   connect(myAutoConstraints, SIGNAL(toggled(bool)), this, SIGNAL(autoConstraints(bool)));
177   aLayout->addWidget(myAutoConstraints);
178
179   QPushButton* aPlaneBtn = new QPushButton(tr("Change sketch plane"), aSecondWgt);
180   connect(aPlaneBtn, SIGNAL(clicked(bool)), SLOT(onChangePlane()));
181   aLayout->addWidget(aPlaneBtn);
182
183   myStackWidget->addWidget(aSecondWgt);
184   //setLayout(aLayout);
185
186   myPreviewPlanes = new PartSet_PreviewPlanes();
187 }
188
189 PartSet_WidgetSketchLabel::~PartSet_WidgetSketchLabel()
190 {
191 }
192
193 bool PartSet_WidgetSketchLabel::setSelection(QList<ModuleBase_ViewerPrsPtr>& theValues,
194                                              const bool theToValidate)
195 {
196   // do not use the given selection if the plane of the sketch has been already set.
197   // If this check is absent, a selected plane in the viewer can be set in the sketch
198   // even if the sketch is built on another plane.
199   if (plane().get())
200     return true;
201
202   ModuleBase_ViewerPrsPtr aPrs = theValues.first();
203   bool aDone = setSelectionInternal(theValues, theToValidate);
204   if (aDone)
205     updateByPlaneSelected(aPrs);
206   return aDone;
207 }
208
209 QList<QWidget*> PartSet_WidgetSketchLabel::getControls() const
210 {
211   QList<QWidget*> aResult;
212   aResult << myStackWidget;
213   return aResult;
214 }
215
216 bool PartSet_WidgetSketchLabel::processSelection()
217 {
218   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
219   if (aPlane.get())
220     return false;
221
222   QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
223
224   if (aSelected.empty())
225     return false;
226   ModuleBase_ViewerPrsPtr aPrs = aSelected.first();
227   bool aDone = setSelectionInternal(aSelected, false);
228   if (aDone) {
229     updateByPlaneSelected(aPrs);
230     updateObject(myFeature);
231   }
232
233   return aDone;
234 }
235
236 void PartSet_WidgetSketchLabel::onShowConstraint(bool theOn)
237 {
238   QCheckBox* aSenderCheckBox = qobject_cast<QCheckBox*>(sender());
239
240   QMap<PartSet_Tools::ConstraintVisibleState, QCheckBox*>::const_iterator
241                           anIt = myShowConstraints.begin(), aLast = myShowConstraints.end();
242
243   PartSet_Tools::ConstraintVisibleState aState = PartSet_Tools::Geometrical;
244   bool aFound = false;
245   for (; anIt != aLast && !aFound; anIt++) {
246     aFound = anIt.value() == aSenderCheckBox;
247     if (aFound)
248       aState = anIt.key();
249   }
250   if (aFound)
251     emit showConstraintToggled(aState, theOn);
252 }
253
254 void PartSet_WidgetSketchLabel::blockAttribute(const AttributePtr& theAttribute,
255                                                const bool& theToBlock, bool& isFlushesActived,
256                                                bool& isAttributeSetInitializedBlocked,
257                                                bool& isAttributeSendUpdatedBlocked)
258 {
259   ModuleBase_WidgetValidated::blockAttribute(theAttribute, theToBlock, isFlushesActived,
260                                              isAttributeSetInitializedBlocked,
261                                              isAttributeSendUpdatedBlocked);
262   // We do not restore the previous state of isAttributeSetInitializedBlocked for each of
263   // attributes. It it is necessary, these states should be append to the method attributes
264   // or stored in the widget
265
266   std::list<AttributePtr> anAttributes = myFeature->data()->attributes("");
267   std::list<AttributePtr>::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end();
268   QStringList aValues;
269   for(; anIt != aLast; anIt++) {
270     AttributePtr anAttribute = *anIt;
271     if (theToBlock)
272       anAttribute->blockSetInitialized(true);
273     else
274       anAttribute->blockSetInitialized(isAttributeSetInitializedBlocked);
275   }
276 }
277
278 bool PartSet_WidgetSketchLabel::setSelectionInternal(
279                                           const QList<ModuleBase_ViewerPrsPtr>& theValues,
280                                           const bool theToValidate)
281 {
282   bool aDone = false;
283   if (theValues.empty()) {
284     // In order to make reselection possible, set empty object and shape should be done
285     setSelectionCustom(std::shared_ptr<ModuleBase_ViewerPrs>(
286                               new ModuleBase_ViewerPrs(ObjectPtr(), GeomShapePtr(), NULL)));
287     aDone = false;
288   }
289   else {
290     // it removes the processed value from the parameters list
291     ModuleBase_ViewerPrsPtr aValue = theValues.first();//.takeFirst();
292     if (!theToValidate || isValidInFilters(aValue)) {
293       myIsSelection = true;
294       aDone = setSelectionCustom(aValue);
295       myIsSelection = false;
296     }
297   }
298
299   return aDone;
300 }
301
302 void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrsPtr& thePrs)
303 {
304   GeomPlanePtr aPlane = plane();
305   if (!aPlane.get())
306     return;
307   // 1. hide main planes if they have been displayed and display sketch preview plane
308   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
309
310   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
311   if (aModule) {
312     CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
313     bool isSetSizeOfView = false;
314     double aSizeOfView = 0;
315     QString aSizeOfViewStr = mySizeOfView->text();
316     if (!aSizeOfViewStr.isEmpty()) {
317       aSizeOfView = aSizeOfViewStr.toDouble(&isSetSizeOfView);
318       if (isSetSizeOfView && aSizeOfView <= 0) {
319         isSetSizeOfView = false;
320       }
321     }
322     aModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, isSetSizeOfView);
323     aModule->sketchMgr()->previewSketchPlane()->createSketchPlane(aSketch, myWorkshop);
324   }
325   // 2. if the planes were displayed, change the view projection
326
327   std::shared_ptr<GeomAPI_Dir> aDir = aPlane->direction();
328   gp_XYZ aXYZ = aDir->impl<gp_Dir>().XYZ();
329   double aTwist = 0.0;
330
331   // Rotate view if the sketcher plane is selected only from preview planes
332   // Preview planes are created only if there is no any shape
333   bool aRotate = Config_PropManager::boolean(SKETCH_TAB_NAME, "rotate_to_plane");
334   if (aRotate) {
335     myWorkshop->viewer()->setViewProjection(aXYZ.X(), aXYZ.Y(), aXYZ.Z(), aTwist);
336   }
337   QString aSizeOfViewStr = mySizeOfView->text();
338   if (!aSizeOfViewStr.isEmpty()) {
339     bool isOk;
340     double aSizeOfView = aSizeOfViewStr.toDouble(&isOk);
341     if (isOk && aSizeOfView > 0) {
342       Handle(V3d_View) aView3d = myWorkshop->viewer()->activeView();
343       if (!aView3d.IsNull()) {
344         Bnd_Box aBndBox;
345         double aHalfSize = aSizeOfView/2.0;
346         aBndBox.Update(-aHalfSize, -aHalfSize, -aHalfSize, aHalfSize, aHalfSize, aHalfSize);
347         aView3d->FitAll(aBndBox, 0.01, false);
348       }
349     }
350   }
351   if (myOpenTransaction) {
352     SessionPtr aMgr = ModelAPI_Session::get();
353     aMgr->finishOperation();
354     myOpenTransaction = false;
355   }
356   // 3. Clear text in the label
357   myStackWidget->setCurrentIndex(1);
358   //myLabel->setText("");
359   //myLabel->setToolTip("");
360   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
361
362   // 5. Clear selection mode and define sketching mode
363   emit planeSelected(plane());
364   // after the plane is selected in the sketch, the sketch selection should be activated
365   // it can not be performed in the sketch label widget because, we don't need to switch off
366   // the selection by any label deactivation, but need to switch it off by stop the sketch
367   myWorkshop->selectionActivate()->updateSelectionFilters();
368   myWorkshop->selectionActivate()->updateSelectionModes();
369
370   if (aModule)
371     aModule->onViewTransformed();
372
373   // 6. Update sketcher actions
374   XGUI_ActionsMgr* anActMgr = aWorkshop->actionsMgr();
375
376   myWorkshop->updateCommandStatus();
377   aWorkshop->selector()->clearSelection();
378   myWorkshop->viewer()->update();
379
380   myRemoveExternal->setVisible(false);
381 }
382
383 std::shared_ptr<GeomAPI_Pln> PartSet_WidgetSketchLabel::plane() const
384 {
385   CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
386   return PartSet_Tools::sketchPlane(aSketch);
387 }
388
389 bool PartSet_WidgetSketchLabel::focusTo()
390 {
391   ModuleBase_Tools::setFocus(myStackWidget, "PartSet_WidgetSketchLabel::focusTo()");
392   return true;
393 }
394
395 void PartSet_WidgetSketchLabel::enableFocusProcessing()
396 {
397   myStackWidget->installEventFilter(this);
398 }
399
400 void PartSet_WidgetSketchLabel::storeAttributeValue(const AttributePtr& theAttribute)
401 {
402   ModuleBase_WidgetValidated::storeAttributeValue(theAttribute);
403 }
404
405 void PartSet_WidgetSketchLabel::restoreAttributeValue(const AttributePtr& theAttribute,
406                                                       const bool theValid)
407 {
408   ModuleBase_WidgetValidated::restoreAttributeValue(theAttribute, theValid);
409
410   // it is not necessary to save the previous plane value because the plane is chosen once
411   DataPtr aData = feature()->data();
412   AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
413     (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
414   if (aSelAttr) {
415     ResultPtr anEmptyResult;
416     GeomShapePtr anEmptyShape;
417     aSelAttr->setValue(anEmptyResult, anEmptyShape);
418   }
419 }
420
421 bool PartSet_WidgetSketchLabel::setSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
422 {
423   if (myIsSelection && myRemoveExternal->isVisible()) {
424     if (myRemoveExternal->isChecked()) {
425       myFeature->customAction(SketchPlugin_Sketch::ACTION_REMOVE_EXTERNAL());
426     }
427   }
428   return fillSketchPlaneBySelection(thePrs);
429 }
430
431 bool PartSet_WidgetSketchLabel::canFillSketch(const ModuleBase_ViewerPrsPtr& thePrs)
432 {
433   bool aCanFillSketch = true;
434   // avoid any selection on sketch object
435   ObjectPtr anObject = thePrs->object();
436   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
437   if (aResult.get()) {
438     FeaturePtr aFeature = ModelAPI_Feature::feature(aResult);
439     if (aFeature->getKind() == SketchPlugin_Sketch::ID())
440       aCanFillSketch = false;
441   }
442   // check plane or planar face of any non-sketch object
443   if (aCanFillSketch) {
444     std::shared_ptr<GeomAPI_Face> aGeomFace;
445
446     GeomShapePtr aGeomShape = thePrs->shape();
447     if ((!aGeomShape.get() || aGeomShape->isNull()) && aResult.get()) {
448       aGeomShape = aResult->shape();
449     }
450
451     if (aGeomShape.get() && aGeomShape->shapeType() == GeomAPI_Shape::FACE) {
452       std::shared_ptr<GeomAPI_Face> aGeomFace(new GeomAPI_Face(aGeomShape));
453       aCanFillSketch = aGeomFace.get() && aGeomFace->isPlanar();
454     }
455     else
456       aCanFillSketch = false;
457   }
458   return aCanFillSketch;
459 }
460
461 bool PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(const ModuleBase_ViewerPrsPtr& thePrs)
462 {
463   bool isOwnerSet = false;
464
465   const GeomShapePtr& aShape = thePrs->shape();
466   std::shared_ptr<GeomAPI_Dir> aDir;
467
468   if (aShape.get() && !aShape->isNull()) {
469     const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
470     aDir = setSketchPlane(aTDShape);
471     isOwnerSet = aDir.get();
472   }
473   if (thePrs->object() && (feature() != thePrs->object())) {
474     FeaturePtr aFeature = ModelAPI_Feature::feature(thePrs->object());
475     DataPtr aData = feature()->data();
476     AttributeSelectionPtr aSelAttr =
477       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
478       (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
479     if (aSelAttr.get()) {
480       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(thePrs->object());
481       if (aRes.get()) {
482         GeomShapePtr aShapePtr;
483         if (!aShape.get() || aShape->isNull()) {  // selection happens in the OCC viewer
484           aShapePtr = ModelAPI_Tools::shape(aRes);
485         }
486         else { // selection happens in OB browser
487           aShapePtr = aShape;
488         }
489         if (aShapePtr.get() && aShapePtr->isFace()) {
490           const TopoDS_Shape& aTDShape = aShapePtr->impl<TopoDS_Shape>();
491           setSketchPlane(aTDShape);
492           aSelAttr->setValue(aRes, aShapePtr);
493           isOwnerSet = true;
494         }
495       }
496       else {
497         aSelAttr->setValue(aFeature, GeomShapePtr());
498         GeomShapePtr aShape = aSelAttr->value();
499         if (!aShape.get() && aSelAttr->contextFeature().get() &&
500           aSelAttr->contextFeature()->firstResult().get()) {
501           aShape = aSelAttr->contextFeature()->firstResult()->shape();
502         }
503         if (aShape.get() && aShape->isPlanar()) {
504           const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
505           setSketchPlane(aTDShape);
506           isOwnerSet = true;
507         }
508       }
509     }
510   }
511   return isOwnerSet;
512 }
513
514 void PartSet_WidgetSketchLabel::activateCustom()
515 {
516   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
517   if (aModule) {
518     bool isBlocked = myAutoConstraints->blockSignals(true);
519     myAutoConstraints->setChecked(aModule->sketchReentranceMgr()->isAutoConstraints());
520     myAutoConstraints->blockSignals(isBlocked);
521   }
522
523   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
524   if (aPlane.get()) {
525     myStackWidget->setCurrentIndex(1);
526     return;
527   }
528
529   myStackWidget->setCurrentIndex(0);
530   bool aBodyIsVisualized = myPreviewPlanes->hasVisualizedBodies(myWorkshop);
531
532   // Clear previous selection mode It is necessary for correct activation of preview planes
533   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
534   XGUI_Displayer* aDisp = aWorkshop->displayer();
535   aWorkshop->selectionActivate()->activateObjects(QIntList(), aDisp->displayedObjects(), false);
536
537   if (!aBodyIsVisualized) {
538     // We have to select a plane before any operation
539     myPreviewPlanes->showPreviewPlanes(myWorkshop);
540     mySizeOfViewWidget->setVisible(true);
541   }
542   else
543     mySizeOfViewWidget->setVisible(false);
544 }
545
546 void PartSet_WidgetSketchLabel::deactivate()
547 {
548   ModuleBase_WidgetValidated::deactivate();
549   bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
550   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
551
552   if (aHidePreview)
553     myWorkshop->viewer()->update();
554
555   if (myOpenTransaction) {
556     SessionPtr aMgr = ModelAPI_Session::get();
557     aMgr->finishOperation();
558     myOpenTransaction = false;
559   }
560 }
561
562 void PartSet_WidgetSketchLabel::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
563 {
564   theModuleSelectionModes = -1;
565   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
566   if (!aPlane.get())
567     theModes << TopAbs_FACE;
568 }
569
570 void PartSet_WidgetSketchLabel::selectionFilters(QIntList& theModuleSelectionFilters,
571                                                  SelectMgr_ListOfFilter& theSelectionFilters)
572 {
573   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
574   if (aPlane.get())
575     return;
576   return ModuleBase_WidgetValidated::selectionFilters(theModuleSelectionFilters,
577                                                       theSelectionFilters);
578 }
579
580 std::shared_ptr<GeomAPI_Dir>
581   PartSet_WidgetSketchLabel::setSketchPlane(const TopoDS_Shape& theShape)
582 {
583   if (theShape.IsNull())
584     return std::shared_ptr<GeomAPI_Dir>();
585
586   // get selected shape
587   std::shared_ptr<GeomAPI_Shape> aGShape(new GeomAPI_Shape);
588   aGShape->setImpl(new TopoDS_Shape(theShape));
589
590   // get plane parameters
591   std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(aGShape));
592   std::shared_ptr<GeomAPI_Pln> aPlane = aFace->getPlane();
593   if (!aPlane.get())
594     return std::shared_ptr<GeomAPI_Dir>();
595   return setSketchPlane(aPlane);
596 }
597
598 std::shared_ptr<GeomAPI_Dir>
599   PartSet_WidgetSketchLabel::setSketchPlane(std::shared_ptr<GeomAPI_Pln> thePlane)
600 {
601   // set plane parameters to feature
602   std::shared_ptr<ModelAPI_Data> aData = feature()->data();
603   double anA, aB, aC, aD;
604   thePlane->coefficients(anA, aB, aC, aD);
605
606   // calculate attributes of the sketch
607   std::shared_ptr<GeomAPI_Dir> aNormDir(new GeomAPI_Dir(anA, aB, aC));
608   std::shared_ptr<GeomAPI_XYZ> aCoords = aNormDir->xyz();
609   std::shared_ptr<GeomAPI_XYZ> aZero(new GeomAPI_XYZ(0, 0, 0));
610   aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero));
611   std::shared_ptr<GeomAPI_Pnt> anOrigPnt(new GeomAPI_Pnt(aCoords));
612   // X axis is preferable to be dirX on the sketch
613   const double tol = Precision::Confusion();
614   bool isX = fabs(fabs(anA) - 1.0) < tol && fabs(aB) < tol && fabs(aC) < tol;
615   std::shared_ptr<GeomAPI_Dir> aTempDir(
616       isX ? new GeomAPI_Dir(0, 1, 0) : new GeomAPI_Dir(1, 0, 0));
617   std::shared_ptr<GeomAPI_Dir> aYDir(new GeomAPI_Dir(aNormDir->cross(aTempDir)));
618   std::shared_ptr<GeomAPI_Dir> aXDir(new GeomAPI_Dir(aYDir->cross(aNormDir)));
619
620   std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
621       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
622   anOrigin->setValue(anOrigPnt);
623   std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
624       aData->attribute(SketchPlugin_Sketch::NORM_ID()));
625   aNormal->setValue(aNormDir);
626   std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
627       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
628   aDirX->setValue(aXDir);
629   std::shared_ptr<GeomAPI_Dir> aDir = thePlane->direction();
630   return aDir;
631 }
632
633 void PartSet_WidgetSketchLabel::onSetPlaneView()
634 {
635   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
636   if (aPlane.get()) {
637     std::shared_ptr<GeomAPI_Dir> aDirection = aPlane->direction();
638     gp_Dir aDir = aDirection->impl<gp_Dir>();
639     if (myViewInverted->isChecked())
640       aDir.Reverse();
641     myWorkshop->viewer()->setViewProjection(aDir.X(), aDir.Y(), aDir.Z(), 0.);
642     PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
643     if (aModule)
644       aModule->onViewTransformed();
645   }
646 }
647
648
649 //******************************************************
650 QList<std::shared_ptr<ModuleBase_ViewerPrs>> PartSet_WidgetSketchLabel::findCircularEdgesInPlane()
651 {
652   QList<std::shared_ptr<ModuleBase_ViewerPrs>> aResult;
653   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
654   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
655   QObjectPtrList aDispObjects = aDisplayer->displayedObjects();
656
657   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
658   foreach(ObjectPtr aObj, aDispObjects) {
659     ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
660     if (aResObj.get()) {
661       GeomShapePtr aShape = aResObj->shape();
662       if (aShape.get()) {
663         GeomAPI_ShapeExplorer aExplorer(aShape, GeomAPI_Shape::EDGE);
664         for(; aExplorer.more(); aExplorer.next()) {
665           GeomShapePtr aEdgeShape = aExplorer.current();
666           GeomAPI_Edge anEdge(aEdgeShape);
667           if ((anEdge.isCircle() || anEdge.isArc() || anEdge.isEllipse()) &&
668                anEdge.isInPlane(aPlane)) {
669             bool isContains = false;
670             // Check that edge is not used.
671             // It is possible that the same edge will be taken from different faces
672             foreach(std::shared_ptr<ModuleBase_ViewerPrs> aPrs, aResult) {
673               GeomAPI_Edge aUsedEdge(aPrs->shape());
674               if (aUsedEdge.isEqual(aEdgeShape)) {
675                 isContains = true;
676                 break;
677               }
678             }
679             if (!isContains) {
680               std::shared_ptr<ModuleBase_ViewerPrs>
681                 aPrs(new ModuleBase_ViewerPrs(aResObj, aEdgeShape));
682               aResult.append(aPrs);
683             }
684           }
685         }
686       }
687     }
688   }
689   return aResult;
690 }
691
692 //******************************************************
693 void PartSet_WidgetSketchLabel::onChangePlane()
694 {
695   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
696   if (aModule) {
697     mySizeOfViewWidget->setVisible(false);
698     myRemoveExternal->setVisible(true);
699     myStackWidget->setCurrentIndex(0);
700
701     bool aBodyIsVisualized = myPreviewPlanes->hasVisualizedBodies(myWorkshop);
702
703     if (!aBodyIsVisualized) {
704       // We have to select a plane before any operation
705       myPreviewPlanes->showPreviewPlanes(myWorkshop);
706     }
707
708     CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
709     PartSet_Tools::nullifySketchPlane(aSketch);
710
711     Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_SketchPlaneFilter);
712     if (!aFilter.IsNull()) {
713       std::shared_ptr<GeomAPI_Pln> aPln;
714       Handle(ModuleBase_ShapeInPlaneFilter)::DownCast(aFilter)->setPlane(aPln);
715     }
716     XGUI_Workshop* aWorkshop = aModule->getWorkshop();
717
718     aWorkshop->selectionActivate()->updateSelectionFilters();
719     aWorkshop->selectionActivate()->updateSelectionModes();
720
721     SessionPtr aMgr = ModelAPI_Session::get();
722     aMgr->startOperation("Change Sketch plane");
723     myOpenTransaction = true;
724   }
725 }
726
727 void PartSet_WidgetSketchLabel::setShowPointsState(bool theState)
728 {
729   bool aBlock = myShowPoints->blockSignals(true);
730   myShowPoints->setChecked(theState);
731   myShowPoints->blockSignals(aBlock);
732 }