1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PartSet_SketcherMgr.cpp
4 // Created: 19 Dec 2014
5 // Author: Vitaly SMETANNIKOV
7 #include "PartSet_SketcherMgr.h"
8 #include "PartSet_SketcherReetntrantMgr.h"
9 #include "PartSet_Module.h"
10 #include "PartSet_WidgetPoint2d.h"
11 #include "PartSet_WidgetPoint2dDistance.h"
12 #include "PartSet_Tools.h"
13 #include "PartSet_WidgetSketchLabel.h"
14 #include "PartSet_WidgetEditor.h"
16 #include <XGUI_ModuleConnector.h>
17 #include <XGUI_Displayer.h>
18 #include <XGUI_Workshop.h>
19 #include <XGUI_ContextMenuMgr.h>
20 #include <XGUI_Selection.h>
21 #include <XGUI_SelectionMgr.h>
22 #include <XGUI_ModuleConnector.h>
23 #include <XGUI_PropertyPanel.h>
24 #include <XGUI_ViewerProxy.h>
25 #include <XGUI_OperationMgr.h>
27 #include <ModuleBase_IPropertyPanel.h>
28 #include <ModuleBase_ISelection.h>
29 #include <ModuleBase_IViewer.h>
30 #include <ModuleBase_IWorkshop.h>
31 #include <ModuleBase_IViewWindow.h>
32 #include <ModuleBase_ModelWidget.h>
33 #include <ModuleBase_Operation.h>
34 #include <ModuleBase_OperationFeature.h>
35 #include <ModuleBase_Operation.h>
36 #include <ModuleBase_WidgetEditor.h>
38 #include <GeomDataAPI_Point2D.h>
40 #include <Events_Loop.h>
42 #include <SketchPlugin_Line.h>
43 #include <SketchPlugin_Sketch.h>
44 #include <SketchPlugin_Point.h>
45 #include <SketchPlugin_Arc.h>
46 #include <SketchPlugin_Circle.h>
47 #include <SketchPlugin_ConstraintLength.h>
48 #include <SketchPlugin_ConstraintDistance.h>
49 #include <SketchPlugin_ConstraintParallel.h>
50 #include <SketchPlugin_ConstraintPerpendicular.h>
51 #include <SketchPlugin_ConstraintRadius.h>
52 #include <SketchPlugin_ConstraintRigid.h>
53 #include <SketchPlugin_ConstraintHorizontal.h>
54 #include <SketchPlugin_ConstraintVertical.h>
55 #include <SketchPlugin_ConstraintEqual.h>
56 #include <SketchPlugin_ConstraintTangent.h>
57 #include <SketchPlugin_ConstraintCoincidence.h>
58 #include <SketchPlugin_ConstraintFillet.h>
59 #include <SketchPlugin_ConstraintMirror.h>
60 #include <SketchPlugin_ConstraintAngle.h>
61 #include <SketchPlugin_ConstraintCollinear.h>
62 #include <SketchPlugin_ConstraintMiddle.h>
63 #include <SketchPlugin_MultiRotation.h>
64 #include <SketchPlugin_MultiTranslation.h>
66 #include <SketcherPrs_Tools.h>
68 #include <SelectMgr_IndexedMapOfOwner.hxx>
69 #include <StdSelect_BRepOwner.hxx>
71 //#include <AIS_DimensionSelectionMode.hxx>
72 #include <AIS_Shape.hxx>
73 #include <AIS_Dimension.hxx>
75 #include <ModelAPI_Events.h>
76 #include <ModelAPI_Session.h>
77 #include <ModelAPI_AttributeString.h>
79 #include <QMouseEvent>
80 #include <QApplication>
82 #include <QMessageBox>
84 //#define DEBUG_DO_NOT_BY_ENTER
86 //#define DEBUG_CURSOR
88 /// Returns list of unique objects by sum of objects from List1 and List2
89 /*QList<ModuleBase_ViewerPrs> getSumList(const QList<ModuleBase_ViewerPrs>& theList1,
90 const QList<ModuleBase_ViewerPrs>& theList2)
92 QList<ModuleBase_ViewerPrs> aRes;
93 foreach (ModuleBase_ViewerPrs aPrs, theList1) {
94 if (!aRes.contains(aPrs))
97 foreach (ModuleBase_ViewerPrs aPrs, theList2) {
98 if (!aRes.contains(aPrs))
104 // Fills the list of features the list of selected presentations.
105 // \param theList a list of selected presentations
106 // \param theSketch a sketch to project a vertex shape of a presentation to the plane
107 // and find the corresponded attribute
108 // \param theFeatureList an output list of features
109 void fillFeatureList(const QList<ModuleBase_ViewerPrs>& theList,
110 const FeaturePtr theSketch,
111 QList<FeaturePtr>& theFeatureList)
113 QList<ModuleBase_ViewerPrs> aRes;
115 QList<ModuleBase_ViewerPrs>::const_iterator anIt = theList.begin(),
116 aLast = theList.end();
117 for (; anIt != aLast; anIt++)
119 ModuleBase_ViewerPrs aPrs = *anIt;
120 FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
121 if (aFeature.get() && !theFeatureList.contains(aFeature))
122 theFeatureList.append(aFeature);
126 /// Fills attribute and result lists by the selected owner. In case if the attribute is found,
127 /// by the owner shape, it is put to the list. Otherwise if type of owner shape is edge, put the function
128 /// result as is to the list of results.
129 /// \param theOwner a viewer selected owner
130 /// \param theFeature a feature, where the attribute is searched
131 /// \param theSketch a current sketch
132 /// \param theSelectedAttribute an output list of attributes
133 /// \param theSelectedResults an output list of edge results
134 void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner,
135 const FeaturePtr& theFeature, const FeaturePtr& theSketch,
136 const ResultPtr& theResult,
137 std::set<AttributePtr>& aSelectedAttributes,
138 std::set<ResultPtr>& aSelectedResults)
140 Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(theOwner);
141 if (aBRepOwner.IsNull())
143 Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(
144 aBRepOwner->Selectable());
145 if (aBRepOwner->HasShape()) {
146 const TopoDS_Shape& aShape = aBRepOwner->Shape();
147 TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
148 if (aShapeType == TopAbs_VERTEX) {
149 AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature,
151 if (aPntAttr.get() != NULL)
152 aSelectedAttributes.insert(aPntAttr);
154 else if (aShapeType == TopAbs_EDGE &&
155 aSelectedResults.find(theResult) == aSelectedResults.end()) {
156 aSelectedResults.insert(theResult);
161 PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
162 : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false),
163 myIsMouseOverWindow(false),
164 myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),
165 myIsPopupMenuActive(false)
167 ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
168 ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
170 myPreviousDrawModeEnabled = true;//aViewer->isSelectionEnabled();
172 connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)),
173 this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*)));
175 connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
176 this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*)));
178 connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
179 this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*)));
181 connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)),
182 this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)));
184 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
185 XGUI_Workshop* aWorkshop = aConnector->workshop();
186 connect(aWorkshop, SIGNAL(applicationStarted()), this, SLOT(onApplicationStarted()));
188 myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
189 myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
192 PartSet_SketcherMgr::~PartSet_SketcherMgr()
194 if (!myPlaneFilter.IsNull())
195 myPlaneFilter.Nullify();
198 void PartSet_SketcherMgr::onEnterViewPort()
200 // 1. if the mouse over window, update the next flag. Do not perform update visibility of
201 // created feature because it should be done in onMouseMove(). Some widgets watch
202 // the mouse move and use the cursor position to update own values. If the presentaion is
203 // redisplayed before this update, the feature presentation jumps from reset value to current.
204 myIsMouseOverWindow = true;
206 #ifdef DEBUG_DO_NOT_BY_ENTER
210 if (canChangeCursor(getCurrentOperation())) {
211 QCursor* aCurrentCursor = QApplication::overrideCursor();
212 if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
213 QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
215 qDebug("onEnterViewPort() : Qt::CrossCursor");
220 if (!isNestedCreateOperation(getCurrentOperation()))
223 operationMgr()->onValidateOperation();
225 // we need change displayed state of the current operation feature
226 // if the feature is presentable, e.g. distance construction. It has no results, so workshop does
227 // not accept a signal about the result created. Nothing is shown until mouse is moved out/in view
228 // port. If the isDisplayed flag is true, the presentable feature is displayed as soon as the
229 // presentation becomes valid and redisplay happens
230 //ModuleBase_Operation* aOperation = getCurrentOperation();
231 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
232 (getCurrentOperation());
234 FeaturePtr aFeature = aFOperation->feature();
235 if (aFeature.get() && aFeature->data()->isValid()) {
236 visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature), false);
241 void PartSet_SketcherMgr::onLeaveViewPort()
243 myIsMouseOverViewProcessed = false;
244 myIsMouseOverWindow = false;
245 // it is important to validate operation here only if sketch entity create operation is active
246 // because at this operation we reacts to the mouse leave/enter view port
247 //operationMgr()->onValidateOperation();
249 #ifdef DEBUG_DO_NOT_BY_ENTER
253 if (canChangeCursor(getCurrentOperation())) {
254 QApplication::restoreOverrideCursor();
256 qDebug("onLeaveViewPort() : None");
260 if (!isNestedCreateOperation(getCurrentOperation()))
263 // the method should be performed if the popup menu is called,
264 // the reset of the current widget should not happen
265 if (myIsPopupMenuActive)
268 operationMgr()->onValidateOperation();
270 // 2. if the mouse IS NOT over window, reset the active widget value and hide the presentation
271 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
272 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
273 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
274 // disable the viewer update in order to avoid visualization of redisplayed feature in viewer
275 // obtained after reset value
276 bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
277 ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
279 anActiveWidget->reset();
281 // hides the presentation of the current operation feature
282 // the feature is to be erased here, but it is correct to call canDisplayObject because
283 // there can be additional check (e.g. editor widget in distance constraint)
284 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
285 (getCurrentOperation());
287 FeaturePtr aFeature = aFOperation->feature();
288 visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
290 // we should update viewer after the presentation are hidden in the viewer
291 // otherwise the reset presentation(line) appears in the viewer(by quick move from viewer to PP)
292 aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
295 void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel()
297 if (!isNestedEditOperation(getCurrentOperation()) ||
298 myModule->sketchReentranceMgr()->isInternalEditActive())
300 // it is necessary to save current selection in order to restore it after the values are modifed
303 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
304 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
305 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
306 myPreviousUpdateViewerEnabled = aDisplayer->enableUpdateViewer(false);
309 void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel()
311 if (!isNestedEditOperation(getCurrentOperation()) ||
312 myModule->sketchReentranceMgr()->isInternalEditActive())
314 // it is necessary to restore current selection in order to restore it after the values are modified
316 myCurrentSelection.clear();
318 // 3. the flag to disable the update viewer should be set in order to avoid blinking in the
319 // viewer happens by deselect/select the modified objects. The flag should be restored after
320 // the selection processing. The update viewer should be also called.
321 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
322 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
323 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
324 aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled);
325 aDisplayer->updateViewer();
328 void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
330 if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent))
333 //get2dPoint(theWnd, theEvent, myClickedPoint);
335 if (!(theEvent->buttons() & Qt::LeftButton))
338 // Clear dragging mode
339 myIsDragging = false;
341 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
342 ModuleBase_IViewer* aViewer = aWorkshop->viewer();
343 if (!aViewer->canDragByMouse())
346 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
347 (getCurrentOperation());
351 if (aFOperation->isEditOperation()) {
352 // If the current widget is a selector, do nothing, it processes the mouse press
353 ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
354 if(anActiveWidget && anActiveWidget->isViewerSelector()) {
359 // Use only for sketch operations
360 if (myCurrentSketch) {
361 if (!PartSet_Tools::sketchPlane(myCurrentSketch))
364 bool isSketcher = isSketchOperation(aFOperation);
365 bool isSketchOpe = isNestedSketchOperation(aFOperation);
367 // Avoid non-sketch operations
368 if ((!isSketchOpe) && (!isSketcher))
371 bool isEditing = aFOperation->isEditOperation();
373 // Ignore creation sketch operation
374 if ((!isSketcher) && (!isEditing))
377 Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
378 if (!aContext.IsNull()) {
379 // MoveTo in order to highlight current object
380 aContext->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
382 // Remember highlighted objects for editing
383 ModuleBase_ISelection* aSelect = aWorkshop->selection();
385 bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
386 storeSelection(!aHasShift);
388 if (myCurrentSelection.empty()) {
389 if (isSketchOpe && (!isSketcher))
390 // commit previous operation
391 if (!aFOperation->commit())
392 aFOperation->abort();
395 // Init flyout point for radius rotation
396 FeaturePtr aFeature = myCurrentSelection.begin().key();
400 get2dPoint(theWnd, theEvent, myCurrentPoint);
403 myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
405 if (aFeature.get() != NULL) {
406 std::shared_ptr<SketchPlugin_Feature> aSPFeature =
407 std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
408 if (aSPFeature.get() && aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID()) {
409 DataPtr aData = aSPFeature->data();
410 AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT());
411 std::shared_ptr<GeomDataAPI_Point2D> aFPAttr =
412 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);
413 aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY);
416 } else if (isSketchOpe && isEditing) {
417 // If selected another object commit current result
418 aFOperation->commit();
421 get2dPoint(theWnd, theEvent, myCurrentPoint);
424 myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
426 // this is temporary commented in order to avoid the following wrong case:
427 // Distance constraint is under edition, double click on the digit -> nothing happens
428 // because QApplication::processEvents() calls onMouseDoubleClick, which try to show editor
429 // but as the prev edit is commited an new one is not started, editor is not shown.
430 // This is necessary in order to finalize previous operation
431 //QApplication::processEvents();
437 void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
439 if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))
442 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
443 ModuleBase_IViewer* aViewer = aWorkshop->viewer();
444 if (!aViewer->canDragByMouse())
446 ModuleBase_Operation* aOp = getCurrentOperation();
448 if (isNestedSketchOperation(aOp)) {
449 //get2dPoint(theWnd, theEvent, myClickedPoint);
451 // Only for sketcher operations
455 myCurrentSelection.clear();
456 /*Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
457 if (!aContext.IsNull()) {
458 // Reselect edited object
459 aContext->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
460 if (theEvent->modifiers() & Qt::ShiftModifier)
461 aContext->ShiftSelect();
470 aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
471 myIsDragging = false;
474 void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
476 if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent))
479 if (isNestedCreateOperation(getCurrentOperation()) && !myIsMouseOverViewProcessed) {
480 myIsMouseOverViewProcessed = true;
481 // 1. perform the widget mouse move functionality and display the presentation
482 // the mouse move should be processed in the widget, if it can in order to visualize correct
483 // presentation. These widgets correct the feature attribute according to the mouse position
484 ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
485 PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(anActiveWidget);
487 aPoint2DWdg->onMouseMove(theWnd, theEvent);
489 PartSet_WidgetPoint2dDistance* aDistanceWdg = dynamic_cast<PartSet_WidgetPoint2dDistance*>
492 aDistanceWdg->onMouseMove(theWnd, theEvent);
494 // the feature is to be erased here, but it is correct to call canDisplayObject because
495 // there can be additional check (e.g. editor widget in distance constraint)
496 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
497 (getCurrentOperation());
499 FeaturePtr aFeature = aFOperation->feature();
500 visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
504 //myClickedPoint.clear();
507 // 1. the current selection is saved in the mouse press method in order to restore it after moving
508 // 2. the enable selection in the viewer should be temporary switched off in order to ignore
509 // mouse press signal in the viewer(it call Select for AIS context and the dragged objects are
510 // deselected). This flag should be restored in the slot, processed the mouse release signal.
512 ModuleBase_Operation* aCurrentOperation = getCurrentOperation();
513 if (!aCurrentOperation)
515 if (isSketchOperation(aCurrentOperation))
516 return; // No edit operation activated
518 Handle(V3d_View) aView = theWnd->v3dView();
519 gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
521 PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, aY);
522 double dX = aX - myCurrentPoint.myCurX;
523 double dY = aY - myCurrentPoint.myCurY;
525 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
526 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
527 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
528 // 3. the flag to disable the update viewer should be set in order to avoid blinking in the
529 // viewer happens by deselect/select the modified objects. The flag should be restored after
530 // the selection processing. The update viewer should be also called.
531 bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
533 static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
534 //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
535 FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(),
536 aLast = myCurrentSelection.end();
537 // 4. the features and attributes modification(move)
538 bool isModified = false;
539 for (; anIt != aLast; anIt++) {
540 FeaturePtr aFeature = anIt.key();
542 std::set<AttributePtr> anAttributes = anIt.value().first;
543 // Process selection by attribute: the priority to the attribute
544 if (!anAttributes.empty()) {
545 std::set<AttributePtr>::const_iterator anAttIt = anAttributes.begin(),
546 anAttLast = anAttributes.end();
547 for (; anAttIt != anAttLast; anAttIt++) {
548 AttributePtr anAttr = *anAttIt;
549 if (anAttr.get() == NULL)
551 std::string aAttrId = anAttr->id();
552 DataPtr aData = aFeature->data();
553 if (aData->isValid()) {
554 std::shared_ptr<GeomDataAPI_Point2D> aPoint =
555 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(aAttrId));
556 if (aPoint.get() != NULL) {
557 bool isImmutable = aPoint->setImmutable(true);
558 aPoint->move(dX, dY);
560 ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent);
561 aPoint->setImmutable(isImmutable);
566 // Process selection by feature
567 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
568 std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
569 if (aSketchFeature) {
570 aSketchFeature->move(dX, dY);
572 ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, aMoveEvent);
576 // the modified state of the current operation should be updated if there are features, which
579 aCurrentOperation->onValuesChanged();
581 Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver
582 //Events_Loop::loop()->flush(aUpdateEvent); // up update events - to redisplay presentations
584 // 5. it is necessary to save current selection in order to restore it after the features moving
586 // 6. restore the update viewer flag and call this update
587 aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
588 aDisplayer->updateViewer();
591 myCurrentPoint.setValue(aX, aY);
595 void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
597 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
598 (getCurrentOperation());
599 if (aFOperation && aFOperation->isEditOperation()) {
600 std::string aId = aFOperation->id().toStdString();
601 if (isDistanceOperation(aFOperation))
603 // Activate dimension value editing on double click
604 ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
605 QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
606 // Find corresponded widget to activate value editing
607 foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
608 if (aWgt->attributeID() == "ConstraintValue") {
609 PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
611 anEditor->showPopupEditor();
619 void PartSet_SketcherMgr::onApplicationStarted()
621 ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
622 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
623 XGUI_Workshop* aWorkshop = aConnector->workshop();
624 PartSet_SketcherReetntrantMgr* aReentranceMgr = myModule->sketchReentranceMgr();
626 XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
627 if (aPropertyPanel) {
628 //connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)),
629 // this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*)));
631 connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)),
632 aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&)));
633 connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)),
634 aReentranceMgr, SLOT(onWidgetActivated()));
637 XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer();
638 connect(aViewerProxy, SIGNAL(enterViewPort()), this, SLOT(onEnterViewPort()));
639 connect(aViewerProxy, SIGNAL(leaveViewPort()), this, SLOT(onLeaveViewPort()));
641 XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();
642 connect(aContextMenuMgr, SIGNAL(beforeContextMenu()), this, SLOT(onBeforeContextMenu()));
643 connect(aContextMenuMgr, SIGNAL(afterContextMenu()), this, SLOT(onAfterContextMenu()));
646 //void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWidget)
648 //if (!myClickedPoint.myIsInitialized)
651 //ModuleBase_Operation* aOperation = getCurrentOperation();
652 // the distance constraint feature should not use the clickedd point
653 // this is workaround in order to don't throw down the flyout point value,
654 // set by execute() method of these type of features
655 //if (isDistanceOperation(aOperation))
658 //PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(theWidget);
660 // aPnt2dWgt->setPoint(myClickedPoint.myCurX, myClickedPoint.myCurY);
664 void PartSet_SketcherMgr::onBeforeContextMenu()
666 myIsPopupMenuActive = true;
669 void PartSet_SketcherMgr::onAfterContextMenu()
671 myIsPopupMenuActive = false;
674 void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent,
677 Handle(V3d_View) aView = theWnd->v3dView();
678 gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
680 PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, anY);
681 thePoint.setValue(aX, anY);
684 void PartSet_SketcherMgr::launchEditing()
686 if (!myCurrentSelection.empty()) {
687 FeaturePtr aFeature = myCurrentSelection.begin().key();
688 std::shared_ptr<SketchPlugin_Feature> aSPFeature =
689 std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
691 myModule->editFeature(aSPFeature);
696 bool PartSet_SketcherMgr::sketchSolverError()
698 bool anError = false;
699 CompositeFeaturePtr aSketch = activeSketch();
701 AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());
702 anError = !aAttributeString->value().empty();
707 QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature)
709 QString anError = "";
710 if (!theFeature.get() || !theFeature->data()->isValid())
713 CompositeFeaturePtr aSketch = activeSketch();
714 if (aSketch.get() && aSketch == theFeature) {
715 AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());
716 anError = aAttributeString->value().c_str();
721 void PartSet_SketcherMgr::clearClickedFlags()
723 //myClickedPoint.clear();
724 myCurrentPoint.clear();
727 const QStringList& PartSet_SketcherMgr::sketchOperationIdList()
729 static QStringList aIds;
730 if (aIds.size() == 0) {
731 aIds << SketchPlugin_Line::ID().c_str();
732 aIds << SketchPlugin_Point::ID().c_str();
733 aIds << SketchPlugin_Arc::ID().c_str();
734 aIds << SketchPlugin_Circle::ID().c_str();
735 aIds << SketchPlugin_ConstraintFillet::ID().c_str();
736 aIds << SketchPlugin_Circle::ID().c_str();
738 // SketchRectangle is a python feature, so its ID is passed just as a string
739 aIds << "SketchRectangle";
740 aIds.append(constraintsIdList());
745 const QStringList& PartSet_SketcherMgr::constraintsIdList()
747 static QStringList aIds;
748 if (aIds.size() == 0) {
749 aIds << SketchPlugin_ConstraintLength::ID().c_str();
750 aIds << SketchPlugin_ConstraintDistance::ID().c_str();
751 aIds << SketchPlugin_ConstraintRigid::ID().c_str();
752 aIds << SketchPlugin_ConstraintRadius::ID().c_str();
753 aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
754 aIds << SketchPlugin_ConstraintParallel::ID().c_str();
755 aIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
756 aIds << SketchPlugin_ConstraintVertical::ID().c_str();
757 aIds << SketchPlugin_ConstraintEqual::ID().c_str();
758 aIds << SketchPlugin_ConstraintTangent::ID().c_str();
759 aIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
760 aIds << SketchPlugin_ConstraintMirror::ID().c_str();
761 aIds << SketchPlugin_ConstraintAngle::ID().c_str();
762 aIds << SketchPlugin_MultiRotation::ID().c_str();
763 aIds << SketchPlugin_MultiTranslation::ID().c_str();
764 aIds << SketchPlugin_ConstraintCollinear::ID().c_str();
765 aIds << SketchPlugin_ConstraintMiddle::ID().c_str();
770 void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
774 theModes.append(SketcherPrs_Tools::Sel_Dimension_Text);
775 theModes.append(SketcherPrs_Tools::Sel_Dimension_Line);
776 theModes.append(SketcherPrs_Tools::Sel_Constraint);
777 theModes.append(TopAbs_VERTEX);
778 theModes.append(TopAbs_EDGE);
781 bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation)
783 return theOperation && theOperation->id().toStdString() == SketchPlugin_Sketch::ID();
786 bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOperation)
788 return theOperation &&
789 PartSet_SketcherMgr::sketchOperationIdList().contains(theOperation->id());
792 bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation)
794 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
796 return aFOperation && !aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation);
799 bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation)
801 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
803 return aFOperation && aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation);
806 bool PartSet_SketcherMgr::isEntity(const std::string& theId)
808 return (theId == SketchPlugin_Line::ID()) ||
809 (theId == SketchPlugin_Point::ID()) ||
810 (theId == SketchPlugin_Arc::ID()) ||
811 (theId == SketchPlugin_Circle::ID());
814 bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation)
816 std::string anId = theOperation ? theOperation->id().toStdString() : "";
818 return isDistanceKind(anId);
821 bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind)
823 return (theKind == SketchPlugin_ConstraintLength::ID()) ||
824 (theKind == SketchPlugin_ConstraintDistance::ID()) ||
825 (theKind == SketchPlugin_ConstraintRadius::ID()) ||
826 (theKind == SketchPlugin_ConstraintAngle::ID());
829 void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
831 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
832 (getCurrentOperation());
836 myModule->onViewTransformed();
838 // Display all sketcher sub-Objects
839 myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFOperation->feature());
840 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
841 aConnector->workshop()->displayer()->activateTrihedron(true);
843 // Hide sketcher result
844 std::list<ResultPtr> aResults = myCurrentSketch->results();
845 std::list<ResultPtr>::const_iterator aIt;
846 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
847 (*aIt)->setDisplayed(false);
849 myCurrentSketch->setDisplayed(false);
851 // Display sketcher objects
852 for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
853 FeaturePtr aFeature = myCurrentSketch->subFeature(i);
854 std::list<ResultPtr> aResults = aFeature->results();
855 std::list<ResultPtr>::const_iterator aIt;
856 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
857 (*aIt)->setDisplayed(true);
859 aFeature->setDisplayed(true);
862 if (myPlaneFilter.IsNull())
863 myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
865 myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);
867 bool aHasPlane = false;
868 std::shared_ptr<GeomAPI_Pln> aPln;
869 if (aFOperation->isEditOperation()) {
870 // If it is editing of sketch then it means that plane is already defined
871 aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
875 myPlaneFilter->setPlane(aPln);
877 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
878 // all sketch objects should be activated in the sketch selection modes by edit operation start
879 // in case of creation operation, there is an active widget, which activates own selection mode
880 if (aFOperation->isEditOperation() && aHasPlane)
881 aConnector->activateModuleSelectionModes();
884 void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
886 myIsMouseOverWindow = false;
887 myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
888 myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
890 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
892 DataPtr aData = myCurrentSketch->data();
893 if (!aData->isValid()) {
894 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
895 // The sketch was aborted
896 myCurrentSketch = CompositeFeaturePtr();
897 myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
899 // Erase all sketcher objects
900 QStringList aSketchIds = sketchOperationIdList();
901 QObjectPtrList aObjects = aDisplayer->displayedObjects();
902 foreach (ObjectPtr aObj, aObjects) {
903 DataPtr aObjData = aObj->data();
904 if (!aObjData->isValid())
905 aObj->setDisplayed(false);
909 // Hide all sketcher sub-Objects
910 for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
911 FeaturePtr aFeature = myCurrentSketch->subFeature(i);
912 std::list<ResultPtr> aResults = aFeature->results();
913 std::list<ResultPtr>::const_iterator aIt;
914 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
915 (*aIt)->setDisplayed(false);
917 aFeature->setDisplayed(false);
919 // Display sketcher result
920 std::list<ResultPtr> aResults = myCurrentSketch->results();
921 std::list<ResultPtr>::const_iterator aIt;
922 Events_Loop* aLoop = Events_Loop::loop();
923 static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
925 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
927 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
928 if (!aFOperation->isDisplayedOnStart(*aIt)) {
929 (*aIt)->setDisplayed(true);
930 // this display event is needed because sketch already may have "displayed" state,
931 // but not displayed while it is still active (issue 613, abort of existing sketch)
932 ModelAPI_EventCreator::get()->sendUpdated(*aIt, aDispEvent);
935 if (!aFOperation->isDisplayedOnStart(myCurrentSketch))
936 myCurrentSketch->setDisplayed(true);
938 myCurrentSketch = CompositeFeaturePtr();
939 myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
941 Events_Loop::loop()->flush(aDispEvent);
943 // restore the module selection modes, which were changed on startSketch
944 aConnector->activateModuleSelectionModes();
945 aConnector->workshop()->displayer()->activateTrihedron(false);
948 void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
950 if (canChangeCursor(theOperation) && myIsMouseOverWindow) {
951 QCursor* aCurrentCursor = QApplication::overrideCursor();
952 if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
953 QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
955 qDebug("startNestedSketch() : Qt::CrossCursor");
961 void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation)
963 myIsMouseOverViewProcessed = true;
964 operationMgr()->onValidateOperation();
965 if (canChangeCursor(theOperation)) {
966 QApplication::restoreOverrideCursor();
968 qDebug("stopNestedSketch() : None");
973 void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation)
975 if (isNestedCreateOperation(theOperation)) {
976 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
979 FeaturePtr aFeature = aFOperation->feature();
980 // it is necessary to check the the feature data validity because
981 // some kind of features are removed by an operation commit(the macro state of a feature)
982 if (aFeature.get() && aFeature->data()->isValid()) {
983 visualizeFeature(aFeature, aFOperation->isEditOperation(), true);
989 void PartSet_SketcherMgr::operationActivatedByPreselection()
991 ModuleBase_Operation* anOperation = getCurrentOperation();
992 if(anOperation && PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) {
993 // Set final definitions if they are necessary
994 //propertyPanelDefined(aOperation);
995 /// Commit sketcher operations automatically
996 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
999 if (PartSet_SketcherMgr::isDistanceOperation(aFOperation)) {
1000 FeaturePtr aFeature = aFOperation->feature();
1001 // editor is shown only if all attribute references are filled by preseletion
1002 bool anAllRefAttrInitialized = true;
1004 std::list<AttributePtr> aRefAttrs = aFeature->data()->attributes(
1005 ModelAPI_AttributeRefAttr::typeId());
1006 std::list<AttributePtr>::const_iterator anIt = aRefAttrs.begin(), aLast = aRefAttrs.end();
1007 for (; anIt != aLast && anAllRefAttrInitialized; anIt++) {
1008 anAllRefAttrInitialized = (*anIt)->isInitialized();
1010 if (anAllRefAttrInitialized) {
1011 // Activate dimension value editing on double click
1012 ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
1013 QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
1014 // Find corresponded widget to activate value editing
1015 foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
1016 if (aWgt->attributeID() == "ConstraintValue") {
1017 // the featue should be displayed in order to find the AIS text position,
1018 // the place where the editor will be shown
1019 aFeature->setDisplayed(true);
1020 /// the execute is necessary to perform in the feature compute for flyout position
1021 aFeature->execute();
1023 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
1024 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1026 PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
1028 int aX = 0, anY = 0;
1030 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1031 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1032 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
1033 AISObjectPtr anAIS = aDisplayer->getAISObject(aFeature);
1034 Handle(AIS_InteractiveObject) anAISIO;
1035 if (anAIS.get() != NULL) {
1036 anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
1038 if (anAIS.get() != NULL) {
1039 Handle(AIS_InteractiveObject) anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
1041 if (!anAISIO.IsNull()) {
1042 Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO);
1043 if (!aDim.IsNull()) {
1044 gp_Pnt aPosition = aDim->GetTextPosition();
1046 ModuleBase_IViewer* aViewer = aWorkshop->viewer();
1047 Handle(V3d_View) aView = aViewer->activeView();
1049 aView->Convert(aPosition.X(), aPosition.Y(), aPosition.Z(), aCX, aCY);
1051 QWidget* aViewPort = aViewer->activeViewPort();
1052 QPoint aGlPoint = aViewPort->mapToGlobal(QPoint(aCX, aCY));
1057 anEditor->setCursorPosition(aX, anY);
1058 anEditor->showPopupEditor(false);
1066 anOperation->commit();
1070 bool PartSet_SketcherMgr::canUndo() const
1072 return isNestedCreateOperation(getCurrentOperation());
1075 bool PartSet_SketcherMgr::canRedo() const
1077 return isNestedCreateOperation(getCurrentOperation());
1080 bool PartSet_SketcherMgr::canEraseObject(const ObjectPtr& theObject) const
1082 bool aCanErase = true;
1083 // when the sketch operation is active, results of sketch sub-feature can not be hidden
1084 if (myCurrentSketch.get()) {
1085 ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
1086 if (aResult.get()) {
1087 // Display sketcher objects
1088 for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) {
1090 FeaturePtr aFeature = myCurrentSketch->subFeature(i);
1091 std::list<ResultPtr> aResults = aFeature->results();
1092 std::list<ResultPtr>::const_iterator anIt;
1093 for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) {
1094 aCanErase = *anIt != aResult;
1102 bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
1104 bool aCanDisplay = true;
1106 bool aHasActiveSketch = activeSketch().get() != NULL;
1107 if (aHasActiveSketch) {
1108 // 1. the sketch feature should not be displayed during the sketch active operation
1109 // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch
1110 // nested features can be visualized
1111 FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1112 if (aFeature.get() != NULL && aFeature == activeSketch()) {
1113 aCanDisplay = false;
1116 else { // there are no an active sketch
1117 // 2. sketch sub-features should not be visualized if the sketch operation is not active
1118 FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1119 if (aFeature.get() != NULL) {
1120 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
1121 std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
1122 if (aSketchFeature.get()) {
1123 aCanDisplay = false;
1128 // 3. the method should not filter the objects, which are not related to the current operation.
1129 // The object is filtered just if it is a current operation feature or this feature result
1130 bool isObjectFound = false;
1131 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1132 (getCurrentOperation());
1134 FeaturePtr aFeature = aFOperation->feature();
1135 if (aFeature.get()) {
1136 std::list<ResultPtr> aResults = aFeature->results();
1137 if (theObject == aFeature)
1138 isObjectFound = true;
1140 std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLast = aResults.end();
1141 for (; anIt != aLast && !isObjectFound; anIt++) {
1142 isObjectFound = *anIt == theObject;
1150 // 4. For created nested feature operation do not display the created feature if
1151 // the mouse curstor leaves the OCC window.
1152 // The correction cases, which ignores this condition:
1153 // a. the property panel values modification
1154 // b. the popup menu activated
1155 // c. widget editor control
1156 #ifndef DEBUG_DO_NOT_BY_ENTER
1157 if (aCanDisplay && isNestedCreateOperation(getCurrentOperation())) {
1158 ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
1159 ModuleBase_WidgetEditor* anEditorWdg = anActiveWidget ? dynamic_cast<ModuleBase_WidgetEditor*>(anActiveWidget) : 0;
1160 // the active widget editor should not influence here. The presentation should be visible always
1161 // when this widget is active.
1162 if (!anEditorWdg && !myIsPopupMenuActive) {
1163 // during a nested create operation, the feature is redisplayed only if the mouse over view
1164 // of there was a value modified in the property panel after the mouse left the view
1165 aCanDisplay = canDisplayCurrentCreatedFeature();
1172 void PartSet_SketcherMgr::processHiddenObject(const std::list<ObjectPtr>& theObjects)
1174 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1175 (getCurrentOperation());
1176 if (aFOperation && myCurrentSketch.get()) {
1177 // find results of the current operation
1178 // these results should not be proposed to be deleted
1179 FeaturePtr anOperationFeature = aFOperation->feature();
1180 std::list<ResultPtr> anOperationResultList = anOperationFeature->results();
1181 std::set<ResultPtr> anOperationResults;
1182 std::list<ResultPtr>::const_iterator aRIt = anOperationResultList.begin(),
1183 aRLast = anOperationResultList.end();
1184 for (; aRIt != aRLast; aRIt++)
1185 anOperationResults.insert(*aRIt);
1187 std::set<FeaturePtr> anObjectsToBeDeleted;
1188 QStringList anObjectsToBeDeletedNames;
1189 std::list<ObjectPtr>::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1190 for (; anIt != aLast; anIt++) {
1191 ObjectPtr anObject = *anIt;
1192 bool aCanErase = true;
1193 // when the sketch operation is active, results of sketch sub-feature can not be hidden
1194 ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
1195 // the result is found between current feature results
1196 if (anOperationResults.find(aResult) != anOperationResults.end())
1199 if (aResult.get()) {
1200 // Display sketcher objects
1201 for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) {
1202 FeaturePtr aFeature = myCurrentSketch->subFeature(i);
1203 std::list<ResultPtr> aResults = aFeature->results();
1204 std::list<ResultPtr>::const_iterator anIt;
1205 for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) {
1206 aCanErase = *anIt != aResult;
1211 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
1212 if (aFeature.get() && anObjectsToBeDeleted.find(aFeature) == anObjectsToBeDeleted.end()) {
1213 anObjectsToBeDeleted.insert(aFeature);
1214 anObjectsToBeDeletedNames.append(aFeature->name().c_str());
1218 if (!anObjectsToBeDeleted.empty()) {
1219 QString aFeatureNames = anObjectsToBeDeletedNames.join(", ");
1220 QString aMessage = tr("The following features have incorrect presentation and \
1221 will be hidden: %1. Would you like to delete them?")
1222 .arg(aFeatureNames);
1223 int anAnswer = QMessageBox::question(qApp->activeWindow(), tr("Features hide"),
1224 aMessage, QMessageBox::Ok | QMessageBox::Cancel,
1225 QMessageBox::Cancel);
1226 if (anAnswer == QMessageBox::Ok) {
1227 QObjectPtrList anObjects;
1228 std::set<FeaturePtr>::const_iterator anIt = anObjectsToBeDeleted.begin(),
1229 aLast = anObjectsToBeDeleted.end();
1230 for (; anIt != aLast; anIt++)
1231 anObjects.append(*anIt);
1232 SessionPtr aMgr = ModelAPI_Session::get();
1233 DocumentPtr aDoc = aMgr->activeDocument();
1234 bool aIsOp = aMgr->isOperation();
1236 aMgr->startOperation();
1237 workshop()->deleteFeatures(anObjects);
1238 //static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
1239 //static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
1240 //Events_Loop::loop()->flush(aDeletedEvent);
1241 //Events_Loop::loop()->flush(aRedispEvent);
1244 aMgr->finishOperation();
1250 bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const
1252 bool aCanDisplay = myIsMouseOverWindow;
1254 ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
1256 aCanDisplay = anActiveWidget->getValueState() == ModuleBase_ModelWidget::Stored;
1261 bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const
1263 return isNestedCreateOperation(theOperation) ||
1264 myModule->sketchReentranceMgr()->isInternalEditActive();
1267 const QMap<PartSet_Tools::ConstraintVisibleState, bool>& PartSet_SketcherMgr::showConstraintStates()
1269 return myIsConstraintsShown;
1272 bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const
1274 bool isFoundObject = false;
1276 FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);
1277 if (anObjectFeature.get()) {
1278 int aSize = myCurrentSketch->numberOfSubs();
1279 for (int i = 0; i < myCurrentSketch->numberOfSubs() && !isFoundObject; i++) {
1280 FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i);
1281 isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature;
1284 return isFoundObject;
1287 void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln)
1289 if (myPlaneFilter.IsNull())
1290 myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
1292 myPlaneFilter->setPlane(thePln);
1295 void PartSet_SketcherMgr::getCurrentSelection(const FeaturePtr& theFeature,
1296 const FeaturePtr& theSketch,
1297 ModuleBase_IWorkshop* theWorkshop,
1298 FeatureToSelectionMap& theSelection)
1300 if (theFeature.get() == NULL)
1303 std::set<AttributePtr> aSelectedAttributes;
1304 std::set<ResultPtr> aSelectedResults;
1306 ModuleBase_IViewer* aViewer = theWorkshop->viewer();
1307 Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
1308 if (!aContext.IsNull()) {
1309 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
1310 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
1312 std::list<ResultPtr> aResults = theFeature->results();
1313 std::list<ResultPtr>::const_iterator aIt;
1314 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt)
1316 ResultPtr aResult = *aIt;
1317 AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
1318 if (aAISObj.get() == NULL)
1320 Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1321 for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
1323 Handle(SelectMgr_EntityOwner) anOwner = aContext->SelectedOwner();
1324 if (anOwner->Selectable() != anAISIO)
1326 getAttributesOrResults(anOwner, theFeature, theSketch, aResult,
1327 aSelectedAttributes, aSelectedResults);
1329 for (aContext->InitDetected(); aContext->MoreDetected(); aContext->NextDetected()) {
1330 Handle(SelectMgr_EntityOwner) anOwner = aContext->DetectedOwner();
1331 if (anOwner.IsNull())
1333 if (anOwner->Selectable() != anAISIO)
1335 getAttributesOrResults(anOwner, theFeature, theSketch, aResult,
1336 aSelectedAttributes, aSelectedResults);
1340 theSelection[theFeature] = std::make_pair(aSelectedAttributes, aSelectedResults);
1343 void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,
1344 const FeaturePtr& theSketch,
1345 ModuleBase_IWorkshop* theWorkshop,
1346 const FeatureToSelectionMap& theSelection,
1347 SelectMgr_IndexedMapOfOwner& theOwnersToSelect)
1349 if (theFeature.get() == NULL)
1352 FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature);
1353 std::set<AttributePtr> aSelectedAttributes = anIt.value().first;
1354 std::set<ResultPtr> aSelectedResults = anIt.value().second;
1356 ModuleBase_IViewer* aViewer = theWorkshop->viewer();
1358 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
1359 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
1361 // 1. found the feature's owners. Check the AIS objects of the constructions
1362 AISObjectPtr aAISObj = aDisplayer->getAISObject(theFeature);
1363 if (aAISObj.get() != NULL && aSelectedAttributes.empty() && aSelectedResults.empty()) {
1364 Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1366 SelectMgr_IndexedMapOfOwner aSelectedOwners;
1367 aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
1368 for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
1369 Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
1370 if (!anOwner.IsNull())
1371 theOwnersToSelect.Add(anOwner);
1375 // 2. found the feature results's owners
1376 std::list<ResultPtr> aResults = theFeature->results();
1377 std::list<ResultPtr>::const_iterator aIt;
1378 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt)
1380 ResultPtr aResult = *aIt;
1381 AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
1382 if (aAISObj.get() == NULL)
1384 Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1386 SelectMgr_IndexedMapOfOwner aSelectedOwners;
1387 aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
1388 for ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) {
1389 Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i));
1390 if ( anOwner.IsNull() || !anOwner->HasShape() )
1392 const TopoDS_Shape& aShape = anOwner->Shape();
1393 TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
1394 if (aShapeType == TopAbs_VERTEX) {
1395 AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch);
1396 if (aPntAttr.get() != NULL &&
1397 aSelectedAttributes.find(aPntAttr) != aSelectedAttributes.end()) {
1398 theOwnersToSelect.Add(anOwner);
1401 else if (aShapeType == TopAbs_EDGE) {
1402 bool aFound = aSelectedResults.find(aResult) != aSelectedResults.end();
1403 if (aSelectedResults.find(aResult) != aSelectedResults.end() &&
1404 theOwnersToSelect.FindIndex(anOwner) <= 0)
1405 theOwnersToSelect.Add(anOwner);
1411 void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect)
1414 connect(theWidget, SIGNAL(beforeValuesChanged()),
1415 this, SLOT(onBeforeValuesChangedInPropertyPanel()));
1416 connect(theWidget, SIGNAL(afterValuesChanged()),
1417 this, SLOT(onAfterValuesChangedInPropertyPanel()));
1420 disconnect(theWidget, SIGNAL(beforeValuesChanged()),
1421 this, SLOT(onBeforeValuesChangedInPropertyPanel()));
1422 disconnect(theWidget, SIGNAL(afterValuesChanged()),
1423 this, SLOT(onAfterValuesChangedInPropertyPanel()));
1427 void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState)
1429 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1430 (getCurrentOperation());
1432 if (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
1433 PartSet_SketcherMgr::isNestedSketchOperation(aFOperation) &&
1434 thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) {
1435 FeaturePtr aFeature = aFOperation->feature();
1436 visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
1441 ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const
1443 return myModule->workshop()->currentOperation();
1446 //**************************************************************
1447 ModuleBase_ModelWidget* PartSet_SketcherMgr::getActiveWidget() const
1449 ModuleBase_ModelWidget* aWidget = 0;
1450 ModuleBase_Operation* anOperation = getCurrentOperation();
1452 ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
1454 aWidget = aPanel->activeWidget();
1459 void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature,
1460 const bool isEditOperation,
1461 const bool isToDisplay,
1462 const bool isFlushRedisplay)
1464 #ifdef DEBUG_DO_NOT_BY_ENTER
1468 if (isEditOperation || !theFeature.get())
1471 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1472 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1474 // 1. change visibility of the object itself, here the presentable object is processed,
1475 // e.g. constraints features
1476 //FeaturePtr aFeature = aFOperation->feature();
1477 std::list<ResultPtr> aResults = theFeature->results();
1479 theFeature->setDisplayed(true);
1481 theFeature->setDisplayed(false);
1483 // change visibility of the object results, e.g. non-constraint features
1484 std::list<ResultPtr>::const_iterator aIt;
1485 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
1487 (*aIt)->setDisplayed(true);
1490 (*aIt)->setDisplayed(false);
1493 if (isFlushRedisplay)
1494 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1497 void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly)
1499 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1500 ModuleBase_ISelection* aSelect = aWorkshop->selection();
1501 QList<ModuleBase_ViewerPrs> aHighlighted = aSelect->getHighlighted();
1503 QList<FeaturePtr> aFeatureList;
1504 if (theHighlightedOnly) {
1505 fillFeatureList(aHighlighted, myCurrentSketch, aFeatureList);
1508 fillFeatureList(aHighlighted, myCurrentSketch, aFeatureList);
1510 QList<ModuleBase_ViewerPrs> aSelected = aSelect->getSelected(ModuleBase_ISelection::AllControls);
1511 fillFeatureList(aSelected, myCurrentSketch, aFeatureList);
1514 // 1. it is necessary to save current selection in order to restore it after the features moving
1515 myCurrentSelection.clear();
1516 QList<FeaturePtr>::const_iterator anIt = aFeatureList.begin(), aLast = aFeatureList.end();
1517 for (; anIt != aLast; anIt++) {
1518 getCurrentSelection(*anIt, myCurrentSketch, aWorkshop, myCurrentSelection);
1520 //qDebug(QString(" storeSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str());
1523 void PartSet_SketcherMgr::restoreSelection()
1525 //qDebug(QString("restoreSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str());
1526 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1527 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1528 FeatureToSelectionMap::const_iterator aSIt = myCurrentSelection.begin(),
1529 aSLast = myCurrentSelection.end();
1530 SelectMgr_IndexedMapOfOwner anOwnersToSelect;
1531 for (; aSIt != aSLast; aSIt++) {
1532 anOwnersToSelect.Clear();
1533 getSelectionOwners(aSIt.key(), myCurrentSketch, aWorkshop, myCurrentSelection,
1535 aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false);
1539 void PartSet_SketcherMgr::onShowConstraintsToggle(bool theState, int theType)
1541 PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType;
1542 if (myIsConstraintsShown.contains(aType) && myIsConstraintsShown[aType] == theState)
1544 if (myCurrentSketch.get() == NULL)
1547 myIsConstraintsShown[aType] = theState;
1549 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1550 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1552 const QStringList& aConstrIds = constraintsIdList();
1553 for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
1554 FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);
1555 std::string aKind = aSubFeature->getKind();
1556 if (aConstrIds.contains(QString(aKind.c_str()))) {
1557 bool isTypedConstraint = false;
1558 if (aType == PartSet_Tools::Dimensional) {
1559 isTypedConstraint = isDistanceKind(aKind);
1562 isTypedConstraint = !isDistanceKind(aKind);
1564 if (isTypedConstraint) {
1566 aSubFeature->setDisplayed(true);
1568 aSubFeature->setDisplayed(false);
1572 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1575 XGUI_Workshop* PartSet_SketcherMgr::workshop() const
1577 ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
1578 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
1579 return aConnector->workshop();
1582 XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const
1584 return workshop()->operationMgr();