Salome HOME
#2309 Possibility to hide faces
[modules/shaper.git] / src / PartSet / PartSet_Module.cpp
1 // Copyright (C) 2014-2017  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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "PartSet_Module.h"
22 #include "PartSet_WidgetSketchLabel.h"
23 #include "PartSet_Validators.h"
24 #include "PartSet_Tools.h"
25 #include "PartSet_PreviewPlanes.h"
26 #include "PartSet_WidgetPoint2d.h"
27 #include "PartSet_WidgetPoint2DFlyout.h"
28 #include "PartSet_WidgetShapeSelector.h"
29 #include "PartSet_WidgetMultiSelector.h"
30 #include "PartSet_WidgetFeaturePointSelector.h"
31 #include "PartSet_WidgetEditor.h"
32 #include "PartSet_WidgetFileSelector.h"
33 #include "PartSet_WidgetSketchCreator.h"
34 #include "PartSet_SketcherMgr.h"
35 #include "PartSet_SketcherReentrantMgr.h"
36 #include "PartSet_ResultSketchPrs.h"
37 #include "PartSet_MenuMgr.h"
38 #include "PartSet_CustomPrs.h"
39 #include "PartSet_IconFactory.h"
40 #include "PartSet_OverconstraintListener.h"
41
42 #include "PartSet_Filters.h"
43 #include "PartSet_FilterInfinite.h"
44
45 #include <PartSetPlugin_Remove.h>
46 #include <PartSetPlugin_Part.h>
47 #include <PartSetPlugin_Duplicate.h>
48
49 #include <ModuleBase_Operation.h>
50 #include <ModuleBase_OperationAction.h>
51 #include <ModuleBase_IViewer.h>
52 #include <ModuleBase_IViewWindow.h>
53 #include <ModuleBase_IPropertyPanel.h>
54 #include <ModuleBase_WidgetChoice.h>
55 #include <ModuleBase_WidgetEditor.h>
56 #include <ModuleBase_WidgetValidated.h>
57 #include <ModuleBase_Tools.h>
58 #include <ModuleBase_OperationFeature.h>
59 #include <ModuleBase_WidgetFactory.h>
60 #include <ModuleBase_OperationDescription.h>
61 #include <ModuleBase_ViewerPrs.h>
62
63 #include <ModelAPI_Object.h>
64 #include <ModelAPI_Events.h>
65 #include <ModelAPI_Validator.h>
66 #include <ModelAPI_Data.h>
67 #include <ModelAPI_Session.h>
68 #include <ModelAPI_ResultBody.h>
69 #include <ModelAPI_AttributeString.h>
70 #include <ModelAPI_AttributeSelectionList.h>
71 #include <ModelAPI_Tools.h>
72 #include <ModelAPI_ResultConstruction.h>
73
74 #include <GeomDataAPI_Point2D.h>
75 #include <GeomDataAPI_Point.h>
76 #include <GeomDataAPI_Dir.h>
77
78 #include <XGUI_ActiveControlMgr.h>
79 #include <XGUI_ActiveControlSelector.h>
80 #include <XGUI_ActionsMgr.h>
81 #include <XGUI_ContextMenuMgr.h>
82 #include <XGUI_CustomPrs.h>
83 #include <XGUI_DataModel.h>
84 #include <XGUI_Displayer.h>
85 #include <XGUI_ErrorMgr.h>
86 #include <XGUI_FacesPanelSelector.h>
87 #include <XGUI_ModuleConnector.h>
88 #include <XGUI_ObjectsBrowser.h>
89 #include <XGUI_OperationMgr.h>
90 #include <XGUI_PropertyPanel.h>
91 #include <XGUI_SelectionMgr.h>
92 #include <XGUI_Tools.h>
93 #include <XGUI_Workshop.h>
94
95 #include <SketchPlugin_ConstraintAngle.h>
96 #include <SketchPlugin_ConstraintLength.h>
97 #include <SketchPlugin_ConstraintDistance.h>
98 #include <SketchPlugin_ConstraintParallel.h>
99 #include <SketchPlugin_ConstraintPerpendicular.h>
100 #include <SketchPlugin_ConstraintRadius.h>
101 #include <SketchPlugin_Feature.h>
102 #include <SketchPlugin_Projection.h>
103 #include <SketchPlugin_Sketch.h>
104
105 #include <SketcherPrs_SymbolPrs.h>
106 #include <SketcherPrs_Coincident.h>
107 #include <SketcherPrs_Tools.h>
108
109 #include <Events_Loop.h>
110 #include <Config_PropManager.h>
111 #include <Config_Keywords.h>
112
113 #include <AIS_Dimension.hxx>
114 #include <AIS_InteractiveObject.hxx>
115 #include <StdSelect_TypeOfFace.hxx>
116 #include <TopoDS_Vertex.hxx>
117 #include <TopoDS.hxx>
118 #include <TopoDS_Shape.hxx>
119 #include <BRep_Tool.hxx>
120
121 #include <QObject>
122 #include <QMouseEvent>
123 #include <QString>
124 #include <QTimer>
125 #include <QApplication>
126 #include <QMessageBox>
127 #include <QMainWindow>
128 #include <QLineEdit>
129 #include <QString>
130
131 #include <GeomAlgoAPI_FaceBuilder.h>
132 #include <GeomDataAPI_Dir.h>
133
134 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>
135
136 #ifdef _DEBUG
137 #include <QDebug>
138 #endif
139
140 /*!Create and return new instance of XGUI_Module*/
141 extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop* theWshop)
142 {
143   return new PartSet_Module(theWshop);
144 }
145
146 PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
147 : ModuleBase_IModule(theWshop),
148   myVisualLayerId(0),
149   myIsOperationIsLaunched(false)
150 {
151   new PartSet_IconFactory();
152
153   mySketchMgr = new PartSet_SketcherMgr(this);
154   mySketchReentrantMgr = new PartSet_SketcherReentrantMgr(theWshop);
155
156   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWshop);
157   XGUI_Workshop* aWorkshop = aConnector->workshop();
158
159   ModuleBase_IViewer* aViewer = theWshop->viewer();
160   connect(aViewer, SIGNAL(keyRelease(ModuleBase_IViewWindow*, QKeyEvent*)),
161           this, SLOT(onKeyRelease(ModuleBase_IViewWindow*, QKeyEvent*)));
162   connect(aViewer, SIGNAL(viewTransformed(int)),
163           SLOT(onViewTransformed(int)));
164   connect(aViewer, SIGNAL(viewCreated(ModuleBase_IViewWindow*)),
165           SLOT(onViewCreated(ModuleBase_IViewWindow*)));
166   myMenuMgr = new PartSet_MenuMgr(this);
167   myCustomPrs = new PartSet_CustomPrs(theWshop);
168
169   myOverconstraintListener = new PartSet_OverconstraintListener(theWshop);
170
171   Events_Loop* aLoop = Events_Loop::loop();
172   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
173
174   mySelectionFilters.Append(new PartSet_GlobalFilter(myWorkshop));
175   mySelectionFilters.Append(new PartSet_FilterInfinite(myWorkshop));
176
177   setDefaultConstraintShown();
178
179   Config_PropManager::registerProp("Visualization", "operation_parameter_color",
180                           "Reference shape wireframe color in operation", Config_Prop::Color,
181                           PartSet_CustomPrs::OPERATION_PARAMETER_COLOR());
182   Config_PropManager::registerProp("Visualization", "operation_result_color",
183                           "Result shape wireframe color in operation", Config_Prop::Color,
184                           PartSet_CustomPrs::OPERATION_RESULT_COLOR());
185   Config_PropManager::registerProp("Visualization", "operation_highlight_color",
186                           "Multi selector item color in operation", Config_Prop::Color,
187                           PartSet_CustomPrs::OPERATION_HIGHLIGHT_COLOR());
188   Config_PropManager::registerProp("Visualization", "operation_remove_feature_color",
189                           "Color of removed feature in operation", Config_Prop::Color,
190                           PartSet_CustomPrs::OPERATION_REMOVE_FEATURE_COLOR());
191   Config_PropManager::registerProp("Visualization", "sketch_preview_plane",
192                           "Color of sketch plane", Config_Prop::Color,
193                           PartSet_CustomPrs::OPERATION_SKETCH_PLANE());
194 }
195
196 PartSet_Module::~PartSet_Module()
197 {
198   SelectMgr_ListIteratorOfListOfFilter aIt(mySelectionFilters);
199   for (; aIt.More(); aIt.Next()) {
200     Handle(SelectMgr_Filter) aFilter = aIt.Value();
201     if (!aFilter.IsNull())
202       aFilter.Nullify();
203   }
204   delete myCustomPrs;
205   delete myOverconstraintListener;
206 }
207
208 void PartSet_Module::activateSelectionFilters()
209 {
210   SelectMgr_ListIteratorOfListOfFilter aIt(mySelectionFilters);
211   for (; aIt.More(); aIt.Next()) {
212     Handle(SelectMgr_Filter) aFilter = aIt.Value();
213     if (!aFilter.IsNull())
214       myWorkshop->viewer()->addSelectionFilter(aFilter);
215   }
216 }
217
218 void PartSet_Module::deactivateSelectionFilters()
219 {
220   SelectMgr_ListIteratorOfListOfFilter aIt(mySelectionFilters);
221   for (; aIt.More(); aIt.Next()) {
222     Handle(SelectMgr_Filter) aFilter = aIt.Value();
223     if (!aFilter.IsNull())
224       myWorkshop->viewer()->removeSelectionFilter(aFilter);
225   }
226 }
227
228 void PartSet_Module::updateActiveSelectionFilters()
229 {
230   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(workshop());
231   XGUI_ActiveControlSelector* anActiveSelector = aWorkshop->activeControlMgr()->activeSelector();
232
233   if (anActiveSelector && anActiveSelector->getType() == XGUI_FacesPanelSelector::Type())
234     sketchMgr()->deactivateSelectionFilters();
235   else
236     sketchMgr()->activateSelectionFilters();
237 }
238
239 void PartSet_Module::storeSelection()
240 {
241   // cash is used only to restore selection, so it should be filled in storeSelection and
242   // after applying immediatelly cleared in restoreSelection
243   myCurrentSelection.clear();
244   sketchMgr()->storeSelection(PartSet_SketcherMgr::ST_SelectType, myCurrentSelection);
245 }
246
247 void PartSet_Module::restoreSelection()
248 {
249   // cash is used only to restore selection, so it should be filled in storeSelection and
250   // after applying immediatelly cleared in restoreSelection
251   sketchMgr()->restoreSelection(myCurrentSelection);
252   myCurrentSelection.clear();
253 }
254
255 void PartSet_Module::registerValidators()
256 {
257   //Registering of validators
258   SessionPtr aMgr = ModelAPI_Session::get();
259   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
260   aFactory->registerValidator("PartSet_DistanceSelection", new PartSet_DistanceSelection);
261   aFactory->registerValidator("PartSet_LengthSelection", new PartSet_LengthSelection);
262   aFactory->registerValidator("PartSet_PerpendicularSelection", new PartSet_PerpendicularSelection);
263   aFactory->registerValidator("PartSet_ParallelSelection", new PartSet_ParallelSelection);
264   aFactory->registerValidator("PartSet_RadiusSelection", new PartSet_RadiusSelection);
265   aFactory->registerValidator("PartSet_RigidSelection", new PartSet_RigidSelection);
266   aFactory->registerValidator("PartSet_CoincidentSelection", new PartSet_CoincidentSelection);
267   aFactory->registerValidator("PartSet_HVDirSelection", new PartSet_HVDirSelection);
268   aFactory->registerValidator("PartSet_TangentSelection", new PartSet_TangentSelection);
269   aFactory->registerValidator("PartSet_FilletSelection", new PartSet_FilletSelection);
270   aFactory->registerValidator("PartSet_AngleSelection", new PartSet_AngleSelection);
271   aFactory->registerValidator("PartSet_EqualSelection", new PartSet_EqualSelection);
272   aFactory->registerValidator("PartSet_CollinearSelection", new PartSet_CollinearSelection);
273   aFactory->registerValidator("PartSet_MiddlePointSelection", new PartSet_MiddlePointSelection);
274   aFactory->registerValidator("PartSet_DifferentObjects", new PartSet_DifferentObjectsValidator);
275   aFactory->registerValidator("PartSet_DifferentPoints", new PartSet_DifferentPointsValidator);
276   aFactory->registerValidator("PartSet_CoincidentAttr", new PartSet_CoincidentAttr);
277   aFactory->registerValidator("PartSet_MultyTranslationSelection",
278     new PartSet_MultyTranslationSelection);
279   aFactory->registerValidator("PartSet_SplitSelection", new PartSet_SplitSelection);
280   aFactory->registerValidator("PartSet_ProjectionSelection", new PartSet_ProjectionSelection);
281 }
282
283 void PartSet_Module::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget,
284                                             const bool isToConnect)
285 {
286   mySketchMgr->connectToPropertyPanel(theWidget, isToConnect);
287 }
288
289 void PartSet_Module::operationCommitted(ModuleBase_Operation* theOperation)
290 {
291   if (sketchMgr()->isNestedSketchOperation(theOperation)) {
292     mySketchMgr->commitNestedSketch(theOperation);
293   }
294   /// deactivate of overconstraint listener should be performed after Sketch commit (#2176)
295   if (PartSet_SketcherMgr::isSketchOperation(theOperation))
296     overconstraintListener()->setActive(false);
297
298   /// Restart sketcher operations automatically
299   if (!mySketchReentrantMgr->operationCommitted(theOperation)) {
300
301     ModuleBase_OperationFeature* aFOperation =
302       dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
303     if (aFOperation && !aFOperation->isEditOperation()) {
304       // the selection is cleared after commit the create operation
305       // in order to do not use the same selected objects in the restarted operation
306       // for common behaviour, the selection is cleared even if the operation is not restarted
307       getWorkshop()->selector()->clearSelection();
308     }
309   }
310 }
311
312 void PartSet_Module::operationAborted(ModuleBase_Operation* theOperation)
313 {
314   /// Restart sketcher operations automatically
315   mySketchReentrantMgr->operationAborted(theOperation);
316   /// deactivate of overconstraint listener should be performed after Sketch abort (#2176)
317   if (PartSet_SketcherMgr::isSketchOperation(theOperation))
318     overconstraintListener()->setActive(false);
319 }
320
321 void PartSet_Module::operationStarted(ModuleBase_Operation* theOperation)
322 {
323   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
324                                                                                 (theOperation);
325   if (aFOperation) {
326     XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(workshop());
327     XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
328
329     ModuleBase_ModelWidget* aFilledWidget = 0;
330     bool aPostonedWidgetActivation = false;
331
332     FeaturePtr aFeature = aFOperation->feature();
333     /// Restart sketcher operations automatically
334     /// it is important to call method of sketch reentrant manager before filling of PP
335     /// because it fills some created feature attributes, these new values should be used
336     /// to fill the property panel
337     mySketchReentrantMgr->operationStarted(theOperation);
338
339     aWorkshop->fillPropertyPanel(aFOperation);
340     // filling the operation values by the current selection
341     // if the operation can be committed after the controls filling, the method perform should
342     // be stopped. Otherwise unnecessary presentations can be shown(e.g. operation prs in sketch)
343     bool isOperationCommitted = false;
344     if (!aFOperation->isEditOperation()) {
345       std::string aGreedAttributeId = ModuleBase_Tools::findGreedAttribute(workshop(), aFeature);
346       // if there is a greed attribute, automatic commit by preselection
347       // for this feature is prohibited
348       aFilledWidget = aFOperation->activateByPreselection(aGreedAttributeId);
349       if (currentOperation() != aFOperation)
350         isOperationCommitted = true;
351       else {
352         if (aGreedAttributeId.empty()) {
353           // a signal should be emitted before the next widget activation
354           // because, the activation of the next widget will give a focus to the widget.
355           // As a result the value of the widget is initialized.
356           // And commit may happens until the value is entered.
357           if (aFilledWidget) {
358             if (mySketchReentrantMgr->canBeCommittedByPreselection())
359               isOperationCommitted = mySketchMgr->operationActivatedByPreselection();
360             // activate the next obligatory widget
361             if (!isOperationCommitted)
362               aPropertyPanel->activateNextWidget(aFilledWidget);
363           }
364         }
365         else { // there is a greed widget
366           const QList<ModuleBase_ModelWidget*>& aWidgets = aPropertyPanel->modelWidgets();
367           std::string aFirstAttributeId = aWidgets.front()->attributeID();
368           // activate next widget after greeded if it is the first widget in the panel
369           // else the first panel widget is already activated by operation start
370           if (aFirstAttributeId == aGreedAttributeId)
371             aPostonedWidgetActivation = true;
372         }
373       }
374     } if (!isOperationCommitted) {
375       aWorkshop->connectToPropertyPanel(true);
376       updateSketcherOnStart(aFOperation);
377       updatePresentationsOnStart(aFOperation);
378
379       // the objects of the current operation should be deactivated
380       QObjectPtrList anObjects;
381       anObjects.append(aFeature);
382       std::list<ResultPtr> aResults;
383       ModelAPI_Tools::allResults(aFeature, aResults);
384       std::list<ResultPtr>::const_iterator aIt;
385       for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
386         anObjects.append(*aIt);
387       }
388       QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
389       for (; anIt != aLast; anIt++)
390         aWorkshop->deactivateActiveObject(*anIt, false);
391       if (anObjects.size() > 0) {
392         XGUI_Displayer* aDisplayer = aWorkshop->displayer();
393         aDisplayer->updateViewer();
394       }
395       /// state of command actions should be updated after displayed objects modification because
396       /// deactivation(for example) of objects may influence on selection in the viewer
397       /// State of command actions may depend on selection in the viewer(e.g. Sketch)
398       workshop()->updateCommandStatus();
399     }
400     if (aPostonedWidgetActivation) {
401       // if the widget is an empty in the chain of activated widgets, the current operation
402       // is restarted. It should be performed after functionality of the operation starting
403       aPropertyPanel->activateNextWidget(aFilledWidget);
404     }
405   }
406 }
407
408 void PartSet_Module::updateSketcherOnStart(ModuleBase_Operation* theOperation)
409 {
410   if (PartSet_SketcherMgr::isSketchOperation(theOperation)) {
411     mySketchMgr->startSketch(theOperation);
412   }
413   else if (sketchMgr()->isNestedSketchOperation(theOperation)) {
414     mySketchMgr->startNestedSketch(theOperation);
415   }
416 }
417
418 void PartSet_Module::updatePresentationsOnStart(ModuleBase_Operation* theOperation)
419 {
420   ModuleBase_OperationFeature* aFOperation =
421     dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
422   if (aFOperation) {
423     myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeArguments, true);
424     myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeResults, true);
425   }
426 }
427
428 void PartSet_Module::operationResumed(ModuleBase_Operation* theOperation)
429 {
430   ModuleBase_IModule::operationResumed(theOperation);
431
432   ModuleBase_OperationFeature* aFOperation =
433     dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
434   if (aFOperation) {
435     myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeArguments, true);
436     myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeResults, true);
437   }
438 }
439
440 void PartSet_Module::operationStopped(ModuleBase_Operation* theOperation)
441 {
442   bool isModifiedArgs = myCustomPrs->deactivate(ModuleBase_IModule::CustomizeArguments, false);
443   bool isModifiedResults = myCustomPrs->deactivate(ModuleBase_IModule::CustomizeResults, false);
444   bool isModified = isModifiedArgs || isModifiedResults;
445
446   if (sketchMgr()->isNestedSketchOperation(theOperation)) {
447     mySketchMgr->stopNestedSketch(theOperation);
448   }
449   else if (PartSet_SketcherMgr::isSketchOperation(theOperation))
450     setDefaultConstraintShown();
451
452   //VSV: Viewer is updated on feature update and redisplay
453   if (isModified) {
454     XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
455     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
456     aDisplayer->updateViewer();
457   }
458
459   QMap<PartSet_Tools::ConstraintVisibleState, bool>::const_iterator
460     anIt = myHasConstraintShown.begin(), aLast = myHasConstraintShown.end();
461   for (; anIt != aLast; anIt++) {
462     mySketchMgr->updateBySketchParameters(anIt.key(), anIt.value());
463   }
464 }
465
466 ModuleBase_Operation* PartSet_Module::currentOperation() const
467 {
468   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
469   XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr();
470   return anOpMgr->currentOperation();
471 }
472
473 bool PartSet_Module::canUndo() const
474 {
475   bool aCanUndo = false;
476   SessionPtr aMgr = ModelAPI_Session::get();
477   if (aMgr->hasModuleDocument() && aMgr->canUndo()) {
478     aCanUndo = !aMgr->isOperation();
479     if (!aCanUndo) // check the enable state additionally by sketch manager
480       aCanUndo = aMgr->canUndo();
481   }
482   return aCanUndo;
483 }
484
485 bool PartSet_Module::canRedo() const
486 {
487   bool aCanRedo = false;
488   SessionPtr aMgr = ModelAPI_Session::get();
489   if (aMgr->hasModuleDocument() && aMgr->canRedo()) {
490     aCanRedo = !aMgr->isOperation();
491     if (!aCanRedo) // check the enable state additionally by sketch manager
492       aCanRedo = aMgr->canRedo();
493   }
494   return aCanRedo;
495 }
496
497 bool PartSet_Module::canApplyAction(const ObjectPtr& theObject, const QString& theActionId) const
498 {
499   bool aValid = true;
500   if (theActionId == "MOVE_CMD") {
501     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
502     if (aFeature) {
503       ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
504       // part features can not be moved in the history.
505       if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
506         aValid = false;
507     }
508   }
509   return aValid;
510 }
511
512 bool PartSet_Module::canEraseObject(const ObjectPtr& theObject) const
513 {
514   // the sketch manager put the restriction to the objects erase
515   return mySketchMgr->canEraseObject(theObject);
516 }
517
518 bool PartSet_Module::canDisplayObject(const ObjectPtr& theObject) const
519 {
520   // the sketch manager put the restriction to the objects display
521   return mySketchMgr->canDisplayObject(theObject);
522 }
523
524 bool PartSet_Module::canUsePreselection(const QString& thePreviousOperationKind,
525                                         const QString& theStartedOperationKind)
526 {
527   if (ModuleBase_IModule::canUsePreselection(thePreviousOperationKind, theStartedOperationKind))
528     return true;
529
530   return mySketchMgr->isNestedSketchFeature(theStartedOperationKind);
531 }
532
533 /*void PartSet_Module::processHiddenObject(const std::list<ObjectPtr>& theObjects)
534 {
535   mySketchMgr->processHiddenObject(theObjects);
536 }*/
537
538 bool PartSet_Module::canActivateSelection(const ObjectPtr& theObject) const
539 {
540   bool aCanActivate = ModuleBase_IModule::canActivateSelection(theObject);
541
542   ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
543   bool isSketchOp = PartSet_SketcherMgr::isSketchOperation(anOperation),
544        isNestedOp = sketchMgr()->isNestedSketchOperation(anOperation);
545   if (isSketchOp || isNestedOp) {
546     // in active sketch operation it is possible to activate operation object in selection
547     // in the edit operation, e.g. points of the line can be moved when the line is edited
548     ModuleBase_OperationFeature* aFOperation =
549       dynamic_cast<ModuleBase_OperationFeature*>(anOperation);
550     aCanActivate = aCanActivate || (aFOperation && aFOperation->isEditOperation());
551   }
552   return aCanActivate;
553 }
554
555 bool PartSet_Module::addViewerMenu(const QMap<QString, QAction*>& theStdActions,
556                                    QWidget* theParent,
557                                    QMap<int, QAction*>& theMenuActions) const
558 {
559   return myMenuMgr->addViewerMenu(theStdActions, theParent, theMenuActions);
560 }
561
562 void PartSet_Module::updateViewerMenu(const QMap<QString, QAction*>& theStdActions)
563 {
564   myMenuMgr->updateViewerMenu(theStdActions);
565 }
566
567 bool PartSet_Module::isActionEnableStateFixed(const int theActionId) const
568 {
569   bool isEnabledFixed = false;
570   if (theActionId == XGUI_ActionsMgr::AcceptAll &&
571       mySketchReentrantMgr->isInternalEditActive())
572     isEnabledFixed = true;
573   return isEnabledFixed;
574 }
575
576 QString PartSet_Module::getFeatureError(const FeaturePtr& theFeature)
577 {
578   QString anError = ModuleBase_IModule::getFeatureError(theFeature);
579   if (anError.isEmpty())
580     anError = sketchMgr()->getFeatureError(theFeature);
581
582   return anError;
583 }
584
585 void PartSet_Module::grantedOperationIds(ModuleBase_Operation* theOperation,
586                                          QStringList& theIds) const
587 {
588   myMenuMgr->grantedOperationIds(theOperation, theIds);
589
590   if (PartSet_SketcherMgr::isSketchOperation(theOperation)) {
591     XGUI_Workshop* aWorkshop = getWorkshop();
592     theIds.append(aWorkshop->contextMenuMgr()->action("DELETE_CMD")->text());
593   }
594 }
595
596 void PartSet_Module::activeSelectionModes(QIntList& theModes)
597 {
598   theModes.clear();
599   if (mySketchMgr->activeSketch().get())
600     PartSet_SketcherMgr::sketchSelectionModes(theModes);
601 }
602
603 void PartSet_Module::customSubShapesSelectionModes(QIntList& theTypes)
604 {
605   if (theTypes.contains(TopAbs_FACE))
606     theTypes.append(SketcherPrs_Tools::Sel_Sketch_Face);
607   if (theTypes.contains(TopAbs_WIRE))
608     theTypes.append(SketcherPrs_Tools::Sel_Sketch_Wire);
609 }
610
611 void PartSet_Module::getGeomSelection(const std::shared_ptr<ModuleBase_ViewerPrs>& theSelected,
612                                       ObjectPtr& theObject, AttributePtr& theAttribute)
613 {
614   ObjectPtr anObject = theSelected->object();
615   GeomShapePtr aShape = theSelected->shape();
616
617   theAttribute = findAttribute(anObject, aShape);
618   // TODO: try to create result if object is an external object
619   theObject = anObject;
620 }
621
622 bool PartSet_Module::isMouseOverWindow()
623 {
624   return mySketchMgr->isMouseOverWindow();
625 }
626
627 bool PartSet_Module::isSketchNeutralPointActivated() const
628 {
629   bool isNeutralPoint = true;
630   if (sketchReentranceMgr()->isInternalEditActive())
631     isNeutralPoint = false;
632   if (myIsOperationIsLaunched)
633     isNeutralPoint = false;
634
635   return isNeutralPoint;
636 }
637
638 void PartSet_Module::closeDocument()
639 {
640   myActivePartIndex = QModelIndex();
641 }
642
643 void PartSet_Module::clearViewer()
644 {
645   myCustomPrs->clearPrs();
646
647   XGUI_Workshop* aWorkshop = getWorkshop();
648   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
649   aDisplayer->deactivateSelectionFilters();
650 }
651
652 void PartSet_Module::propertyPanelDefined(ModuleBase_Operation* theOperation)
653 {
654   ModuleBase_OperationFeature* aFOperation =
655     dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
656   if (!aFOperation)
657     return;
658
659   ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
660   // we have to manually activate the sketch label in edit mode
661   if (PartSet_SketcherMgr::isSketchOperation(aFOperation) &&  (aFOperation->isEditOperation()))
662     aPanel->activateWidget(aPanel->modelWidgets().first());
663 }
664
665 bool PartSet_Module::createWidgets(ModuleBase_Operation* theOperation,
666                                    QList<ModuleBase_ModelWidget*>& theWidgets) const
667 {
668   bool aProcessed = false;
669
670   ModuleBase_OperationFeature* aFOperation =
671     dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
672   XGUI_Workshop* aWorkshop = getWorkshop();
673   XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
674   if (mySketchMgr->activeSketch().get() && aFOperation && aPropertyPanel) {
675     ModuleBase_ISelection* aSelection = workshop()->selection();
676     // click on a point in sketch leads here with the point is highlighted, not yet selected
677     QList<ModuleBase_ViewerPrsPtr> aPreselection = aSelection->getHighlighted();
678     if (aPreselection.size() == 1) {
679       ModuleBase_ViewerPrsPtr aSelectedPrs = aPreselection[0];
680       ObjectPtr anObject = aSelectedPrs->object();
681
682       FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
683       FeaturePtr anOpFeature = aFOperation->feature();
684       GeomShapePtr aShape = aSelectedPrs->shape();
685       // click on the digit of dimension constrain comes here
686       // with an empty shape, so we need the check
687       if (aFeature == anOpFeature && aShape.get() && !aShape->isNull()) {
688         // if feature has only one result and shape of result is equal to selected shape
689         // this attribute is not processed. It is a case of Sketch Point.
690         if (aFeature->results().size() == 1) {
691           ResultPtr aResult = aFeature->results().front();
692           if (aResult.get() && aResult->shape()->isEqual(aShape))
693             return aProcessed;
694         }
695         const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
696         AttributePtr anAttribute = PartSet_Tools::findAttributeBy2dPoint(anObject, aTDShape,
697                                                                mySketchMgr->activeSketch());
698         if (anAttribute.get()) {
699           QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
700           ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), workshop());
701
702           const std::string anAttributeId = anAttribute->id();
703           aFactory.createWidget(aPropertyPanel->contentWidget(), anAttributeId);
704
705           theWidgets = aFactory.getModelWidgets();
706           // it is possible that the point does not present in XML definition,
707           // in this case, we assume that it is not processed by this module
708           // e.g. "Intersection point" feature
709           aProcessed = !theWidgets.isEmpty();
710         }
711       }
712     }
713   }
714   return aProcessed;
715 }
716
717 void PartSet_Module::onSelectionChanged()
718 {
719   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
720   if (!aOperation)
721     return;
722
723   bool isSketcherOp = false;
724   // An edit operation is enable only if the current opeation is the sketch operation
725   if (mySketchMgr->activeSketch()) {
726     if (PartSet_Tools::sketchPlane(mySketchMgr->activeSketch()))
727       isSketcherOp = PartSet_SketcherMgr::isSketchOperation(aOperation);
728   }
729   if (isSketcherOp) {
730     // Editing of constraints can be done on selection
731     ModuleBase_ISelection* aSelect = myWorkshop->selection();
732     QList<ModuleBase_ViewerPrsPtr> aSelected = aSelect->getSelected();
733     if (aSelected.size() == 1) {
734       ModuleBase_ViewerPrsPtr aPrs = aSelected.first();
735       ObjectPtr aObject = aPrs->object();
736       FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
737       if (aFeature) {
738         std::string aId = aFeature->getKind();
739         if ((aId == SketchPlugin_ConstraintRadius::ID()) ||
740             (aId == SketchPlugin_ConstraintLength::ID()) ||
741             (aId == SketchPlugin_ConstraintDistance::ID()) ||
742             (aId == SketchPlugin_ConstraintAngle::ID())) {
743           editFeature(aFeature);
744         }
745       }
746     }
747   }
748 }
749
750 void PartSet_Module::onKeyRelease(ModuleBase_IViewWindow* theWnd, QKeyEvent* theEvent)
751 {
752   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
753   XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr();
754   anOpMgr->onKeyReleased(theWnd->viewPort(), theEvent);
755 }
756
757 ModuleBase_ModelWidget* PartSet_Module::createWidgetByType(const std::string& theType,
758                                                            QWidget* theParent,
759                                                            Config_WidgetAPI* theWidgetApi)
760 {
761   ModuleBase_IWorkshop* aWorkshop = workshop();
762   XGUI_Workshop* aXUIWorkshop = getWorkshop();
763   ModuleBase_ModelWidget* aWgt = NULL;
764   if (theType == "sketch-start-label") {
765     PartSet_WidgetSketchLabel* aLabelWgt = new PartSet_WidgetSketchLabel(theParent, aWorkshop,
766                                                                theWidgetApi, myHasConstraintShown);
767     connect(aLabelWgt, SIGNAL(planeSelected(const std::shared_ptr<GeomAPI_Pln>&)),
768       mySketchMgr, SLOT(onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>&)));
769     connect(aLabelWgt, SIGNAL(showConstraintToggled(int, bool)),
770       mySketchMgr, SLOT(onShowConstraintsToggle(int, bool)));
771     aWgt = aLabelWgt;
772   } else if (theType == "sketch-2dpoint_selector") {
773     PartSet_WidgetPoint2D* aPointWgt = new PartSet_WidgetPoint2D(theParent, aWorkshop,
774                                                                  theWidgetApi);
775     aPointWgt->setSketch(mySketchMgr->activeSketch());
776     connect(aPointWgt, SIGNAL(vertexSelected()), sketchReentranceMgr(), SLOT(onVertexSelected()));
777     aWgt = aPointWgt;
778   }else if (theType == "sketch-2dpoint_flyout_selector") {
779     PartSet_WidgetPoint2DFlyout* aPointWgt = new PartSet_WidgetPoint2DFlyout(theParent, aWorkshop,
780                                                                              theWidgetApi);
781     aPointWgt->setSketch(mySketchMgr->activeSketch());
782     connect(aPointWgt, SIGNAL(vertexSelected()), sketchReentranceMgr(), SLOT(onVertexSelected()));
783     aWgt = aPointWgt;
784   } else if (theType == "sketch_shape_selector") {
785     PartSet_WidgetShapeSelector* aShapeSelectorWgt =
786                           new PartSet_WidgetShapeSelector(theParent, aWorkshop, theWidgetApi);
787     aShapeSelectorWgt->setSketcher(mySketchMgr->activeSketch());
788     aWgt = aShapeSelectorWgt;
789   } else if (theType == "sketch_multi_selector") {
790     PartSet_WidgetMultiSelector* aShapeSelectorWgt =
791                           new PartSet_WidgetMultiSelector(theParent, aWorkshop, theWidgetApi);
792     aShapeSelectorWgt->setSketcher(mySketchMgr->activeSketch());
793     aWgt = aShapeSelectorWgt;
794   }
795   else if (theType == "sketch_feature_point_selector") {
796     PartSet_WidgetFeaturePointSelector* aPointSelectorWgt =
797             new PartSet_WidgetFeaturePointSelector(theParent, aWorkshop, theWidgetApi);
798     aPointSelectorWgt->setSketcher(mySketchMgr->activeSketch());
799     aWgt = aPointSelectorWgt;
800   }
801   else if (theType == WDG_DOUBLEVALUE_EDITOR) {
802     aWgt = new PartSet_WidgetEditor(theParent, aWorkshop, theWidgetApi);
803   } else if (theType == "export_file_selector") {
804     aWgt = new PartSet_WidgetFileSelector(theParent, aWorkshop, theWidgetApi);
805   } else if (theType == "sketch_launcher") {
806     aWgt = new PartSet_WidgetSketchCreator(theParent, this, theWidgetApi);
807   } else if (theType == "module_choice") {
808     aWgt = new ModuleBase_WidgetChoice(theParent, theWidgetApi);
809     connect(aWgt, SIGNAL(itemSelected(ModuleBase_ModelWidget*, int)),
810             this, SLOT(onChoiceChanged(ModuleBase_ModelWidget*, int)));
811   }
812   return aWgt;
813 }
814
815 ModuleBase_ModelWidget* PartSet_Module::activeWidget() const
816 {
817   ModuleBase_ModelWidget* anActiveWidget = 0;
818
819   anActiveWidget = mySketchReentrantMgr->internalActiveWidget();
820   if (!anActiveWidget) {
821     ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
822     if (aOperation) {
823       ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
824       anActiveWidget = aPanel ? aPanel->activeWidget() : 0;
825     }
826   }
827   return anActiveWidget;
828 }
829
830 bool PartSet_Module::deleteObjects()
831 {
832   bool isProcessed = false;
833
834   XGUI_Workshop* aWorkshop = getWorkshop();
835   XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
836
837   //SessionPtr aMgr = ModelAPI_Session::get();
838   // 1. check whether the delete should be processed in the module
839   ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
840   bool isSketchOp = PartSet_SketcherMgr::isSketchOperation(anOperation),
841        isNestedOp = sketchMgr()->isNestedSketchOperation(anOperation);
842   if (isSketchOp || isNestedOp) {
843     isProcessed = true;
844     // 2. find selected presentations
845     // selected objects should be collected before the current operation abort because
846     // the abort leads to selection lost on constraint objects. It can be corrected after #386 issue
847     ModuleBase_ISelection* aSel = workshop()->selection();
848     QObjectPtrList aSelectedObj = aSel->selectedPresentations();
849     // if there are no selected objects in the viewer, that means that the selection in another
850     // place cased this method. It is necessary to return the false value to understande in above
851     // method that delete is not processed
852     if (aSelectedObj.count() == 0)
853       return false;
854
855     // avoid delete of the objects, which are not belong to the current sketch
856     // in order to do not delete results of other sketches
857     QObjectPtrList aSketchObjects;
858     QObjectPtrList::const_iterator anIt = aSelectedObj.begin(), aLast = aSelectedObj.end();
859     for ( ; anIt != aLast; anIt++) {
860       ObjectPtr anObject = *anIt;
861       if (mySketchMgr->isObjectOfSketch(anObject)) {
862         // sketch feature should be used in this list because workshop deletes features only
863         // results are skipped
864         FeaturePtr aSketchFeature = ModelAPI_Feature::feature(anObject);
865         aSketchObjects.append(aSketchFeature);
866       }
867     }
868     // if the selection contains only local selected presentations from other sketches,
869     // the Delete operation should not be done at all
870     if (aSketchObjects.size() == 0)
871       return true;
872
873     // 3. start operation
874     QString aDescription = aWorkshop->contextMenuMgr()->action("DELETE_CMD")->text();
875     ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, this);
876
877     // the active nested sketch operation should be aborted unconditionally
878     // the Delete action should be additionally granted for the Sketch operation
879     // in order to do not abort/commit it
880     bool isCommitted;
881     if (!anOpMgr->canStartOperation(anOpAction->id(), isCommitted))
882       return true; // the objects are processed but can not be deleted
883
884     anOpMgr->startOperation(anOpAction);
885
886     // WORKAROUND, should be done to avoid viewer highlight update after deletetion of objects
887     // the problem is in AIS Dimensions recompute
888     // if a line and the dim are removed, line is the first
889     // it causes the AIS recompute, where the base line is null,
890     // the result is empty AIS in the viewer
891     XGUI_Tools::workshop(myWorkshop)->selector()->clearSelection();
892
893     // 4. delete features
894     // sketch feature should be skipped, only sub-features can be removed
895     // when sketch operation is active
896     aWorkshop->deleteFeatures(aSketchObjects);
897     // 5. stop operation
898     anOpMgr->commitOperation();
899   }
900   return isProcessed;
901 }
902
903 void PartSet_Module::editFeature(FeaturePtr theFeature)
904 {
905   storeConstraintsState(theFeature->getKind());
906   ModuleBase_IModule::editFeature(theFeature);
907 }
908
909 bool PartSet_Module::canCommitOperation() const
910 {
911   return true;
912 }
913
914 void PartSet_Module::launchOperation(const QString& theCmdId, const bool& isStartAfterCommitOnly)
915 {
916   myIsOperationIsLaunched = true;
917   storeConstraintsState(theCmdId.toStdString());
918   updateConstraintsState(theCmdId.toStdString());
919
920   ModuleBase_IModule::launchOperation(theCmdId, isStartAfterCommitOnly);
921
922   myIsOperationIsLaunched = false;
923 }
924
925 void PartSet_Module::storeConstraintsState(const std::string& theFeatureKind)
926 {
927   if (myWorkshop->currentOperation() &&
928       myWorkshop->currentOperation()->id().toStdString() == SketchPlugin_Sketch::ID()) {
929     const QMap<PartSet_Tools::ConstraintVisibleState, bool>& aShownStates =
930                                                   mySketchMgr->showConstraintStates();
931     myHasConstraintShown = aShownStates;
932   }
933 }
934
935 void PartSet_Module::updateConstraintsState(const std::string& theFeatureKind)
936 {
937   if (PartSet_SketcherMgr::constraintsIdList().contains(theFeatureKind.c_str()) ||
938       PartSet_SketcherMgr::replicationsIdList().contains(theFeatureKind.c_str())) {
939     // Show constraints if a constraint was anOperation
940     mySketchMgr->updateBySketchParameters(PartSet_Tools::Geometrical, true);
941     mySketchMgr->updateBySketchParameters(PartSet_Tools::Dimensional, true);
942     mySketchMgr->updateBySketchParameters(PartSet_Tools::Expressions,
943                                           myHasConstraintShown[PartSet_Tools::Expressions]);
944   }
945 }
946
947 void PartSet_Module::onObjectDisplayed(ObjectPtr theObject, AISObjectPtr theAIS)
948 {
949   Handle(AIS_InteractiveObject) anAIS = theAIS->impl<Handle(AIS_InteractiveObject)>();
950   if (!anAIS.IsNull()) {
951     bool aToUseZLayer = false;
952     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
953     if (aFeature.get() && PartSet_Tools::findRefsToMeFeature(aFeature,
954                                                         SketchPlugin_Projection::ID()))
955       aToUseZLayer = true;
956     Handle(AIS_InteractiveContext) aCtx = anAIS->GetContext();
957     Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAIS);
958     if (!aDim.IsNull()) {
959       aToUseZLayer = true;
960     } else {
961       Handle(SketcherPrs_SymbolPrs) aCons = Handle(SketcherPrs_SymbolPrs)::DownCast(anAIS);
962       if (!aCons.IsNull())
963       aToUseZLayer = true;
964     }
965     aCtx->SetZLayer(anAIS, myVisualLayerId);
966   }
967 }
968
969 void PartSet_Module::onBeforeObjectErase(ObjectPtr theObject, AISObjectPtr theAIS)
970 {
971   // this is obsolete
972   // it should be recomputed in order to disappear in the viewer if the corresponded object
973   // is erased
974   //if (myCustomPrs->isActive())
975   //  myCustomPrs->redisplay(theObject, false);
976 }
977
978 void PartSet_Module::onViewTransformed(int theTrsfType)
979 {
980   // Set length of arrows constant in pixel size
981   // if the operation is panning or rotate or panglobal then do nothing
982   if ((theTrsfType == 1) || (theTrsfType == 3) || (theTrsfType == 4))
983     return;
984   ModuleBase_IViewer* aViewer = myWorkshop->viewer();
985   Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
986   if (aContext.IsNull())
987     return;
988
989   //Handle(V3d_View) aView = aViewer->activeView();
990
991   XGUI_Workshop* aWorkshop = getWorkshop();
992   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
993   Handle(V3d_Viewer) aV3dViewer = aContext->CurrentViewer();
994   Handle(V3d_View) aView;
995   double aScale = 0;
996   for (aV3dViewer->InitDefinedViews();
997        aV3dViewer->MoreDefinedViews();
998        aV3dViewer->NextDefinedViews()) {
999     Handle(V3d_View) aV = aV3dViewer->DefinedView();
1000     double aS = aV->Scale();
1001     if (aS > aScale) {
1002       aScale = aS;
1003       aView = aV;
1004     }
1005   }
1006   if (aView.IsNull())
1007     return;
1008
1009   ModuleBase_Operation* aCurrentOperation = myWorkshop->currentOperation();
1010   if (aCurrentOperation &&
1011     (PartSet_SketcherMgr::isSketchOperation(aCurrentOperation) ||
1012      sketchMgr()->isNestedSketchOperation(aCurrentOperation)))
1013   {
1014     double aLen = aView->Convert(SketcherPrs_Tools::getConfigArrowSize());
1015
1016     double aPrevLen = SketcherPrs_Tools::getArrowSize();
1017     SketcherPrs_Tools::setArrowSize(aLen);
1018     const double aCurScale = aViewer->activeView()->Camera()->Scale();
1019     aViewer->SetScale(aViewer->activeView(), aCurScale);
1020     bool isModified = false;
1021     QList<AISObjectPtr> aPrsList = aDisplayer->displayedPresentations();
1022     foreach (AISObjectPtr aAIS, aPrsList) {
1023       Handle(AIS_InteractiveObject) aAisObj = aAIS->impl<Handle(AIS_InteractiveObject)>();
1024
1025       Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(aAisObj);
1026       if (!aDim.IsNull()) {
1027         aDim->DimensionAspect()->ArrowAspect()->SetLength(aLen);
1028         aContext->Redisplay(aDim, false);
1029         isModified = true;
1030       }
1031     }
1032     if (isModified)
1033       aDisplayer->updateViewer();
1034   }
1035 }
1036
1037 bool PartSet_Module::isCustomPrsActivated(const ModuleBase_CustomizeFlag& theFlag) const
1038 {
1039   return myCustomPrs->isActive(theFlag);
1040 }
1041
1042 void PartSet_Module::activateCustomPrs(const FeaturePtr& theFeature,
1043                                        const ModuleBase_CustomizeFlag& theFlag,
1044                                        const bool theUpdateViewer)
1045 {
1046   myCustomPrs->activate(theFeature, theFlag, theUpdateViewer);
1047 }
1048
1049 void PartSet_Module::deactivateCustomPrs(const ModuleBase_CustomizeFlag& theFlag,
1050                                          const bool theUpdateViewer)
1051 {
1052   myCustomPrs->deactivate(theFlag, theUpdateViewer);
1053 }
1054
1055 bool PartSet_Module::customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
1056                                            std::shared_ptr<GeomAPI_ICustomPrs> theCustomPrs)
1057 {
1058   bool aCustomized = false;
1059
1060   XGUI_Workshop* aWorkshop = getWorkshop();
1061   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
1062   ObjectPtr anObject = aDisplayer->getObject(thePrs);
1063   if (!anObject)
1064     return aCustomized;
1065
1066   if (!theResult.get()) {
1067     std::vector<int> aColor;
1068     XGUI_CustomPrs::getDefaultColor(anObject, true, aColor);
1069     if (!aColor.empty()) {
1070       aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
1071     }
1072   }
1073   // customize dimentional constrains
1074   sketchMgr()->customizePresentation(anObject);
1075
1076   return aCustomized;
1077 }
1078
1079 bool PartSet_Module::afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
1080                                                 AISObjectPtr thePrs,
1081                                                 GeomCustomPrsPtr theCustomPrs)
1082 {
1083   bool aCustomized = false;
1084
1085   XGUI_Workshop* aWorkshop = getWorkshop();
1086   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
1087   ObjectPtr anObject = aDisplayer->getObject(thePrs);
1088   if (!anObject)
1089     return aCustomized;
1090
1091   std::vector<int> aColor;
1092   bool aUseCustomColor = true;
1093   if (aUseCustomColor)
1094     myOverconstraintListener->getCustomColor(anObject, aColor);
1095   // customize sketch symbol presentation
1096   Handle(AIS_InteractiveObject) anAISIO = thePrs->impl<Handle(AIS_InteractiveObject)>();
1097   if (!anAISIO.IsNull()) {
1098     if (!Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO).IsNull()) {
1099       Handle(SketcherPrs_SymbolPrs) aPrs = Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO);
1100       if (!aPrs.IsNull()) {
1101         aPrs->SetCustomColor(aColor);
1102         aCustomized = true;
1103       }
1104     } else if (!Handle(SketcherPrs_Coincident)::DownCast(anAISIO).IsNull()) {
1105       Handle(SketcherPrs_Coincident) aPrs = Handle(SketcherPrs_Coincident)::DownCast(anAISIO);
1106       if (!aPrs.IsNull()) {
1107         aPrs->SetCustomColor(aColor);
1108         aCustomized = true;
1109       }
1110     }
1111   }
1112   // customize sketch dimension constraint presentation
1113   if (!aCustomized) {
1114     if (!aColor.empty()) { // otherwise presentation has the default color
1115       aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
1116     }
1117   }
1118   return aCustomized;
1119 }
1120
1121 bool PartSet_Module::customizeObject(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag,
1122                                      const bool theUpdateViewer)
1123 {
1124   bool isRedisplayed = false;
1125   if (myCustomPrs->isActive(theFlag))
1126     isRedisplayed = myCustomPrs->redisplay(theObject, theFlag, theUpdateViewer);
1127
1128   return isRedisplayed;
1129 }
1130
1131 void PartSet_Module::customizeObjectBrowser(QWidget* theObjectBrowser)
1132 {
1133   XGUI_ObjectsBrowser* aOB = dynamic_cast<XGUI_ObjectsBrowser*>(theObjectBrowser);
1134   if (aOB) {
1135     QLabel* aLabel = aOB->activeDocLabel();
1136     aLabel->installEventFilter(myMenuMgr);
1137     connect(aLabel, SIGNAL(customContextMenuRequested(const QPoint&)),
1138           SLOT(onActiveDocPopup(const QPoint&)));
1139     aOB->treeView()->setExpandsOnDoubleClick(false);
1140     connect(aOB->treeView(), SIGNAL(doubleClicked(const QModelIndex&)),
1141       SLOT(onTreeViewDoubleClick(const QModelIndex&)));
1142
1143     Events_Loop* aLoop = Events_Loop::loop();
1144     aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
1145   }
1146 }
1147
1148 void PartSet_Module::onActiveDocPopup(const QPoint& thePnt)
1149 {
1150   SessionPtr aMgr = ModelAPI_Session::get();
1151   QAction* aActivatePartAction = myMenuMgr->action("ACTIVATE_PARTSET_CMD");
1152
1153   XGUI_Workshop* aWorkshop = getWorkshop();
1154   QLabel* aHeader = aWorkshop->objectBrowser()->activeDocLabel();
1155
1156   aActivatePartAction->setEnabled((aMgr->activeDocument() != aMgr->moduleDocument()));
1157
1158   QMenu aMenu;
1159   aMenu.addAction(aActivatePartAction);
1160   aMenu.exec(aHeader->mapToGlobal(thePnt));
1161 }
1162
1163 Handle(AIS_InteractiveObject) PartSet_Module::createPresentation(const ResultPtr& theResult)
1164 {
1165   return mySketchMgr->createPresentation(theResult);
1166 }
1167
1168
1169 ObjectPtr PartSet_Module::findPresentedObject(const AISObjectPtr& theAIS) const
1170 {
1171   ObjectPtr anObject;
1172   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
1173   if (aOperation) {
1174     /// If last line finished on vertex the lines creation sequence has to be break
1175     ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
1176     if (aPanel) {
1177       ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
1178       // if there is an active widget, find the presented object in it
1179       if (!anActiveWidget)
1180         anActiveWidget = aPanel->preselectionWidget();
1181
1182       ModuleBase_WidgetValidated* aWidgetValidated = dynamic_cast<ModuleBase_WidgetValidated*>
1183                                                                              (anActiveWidget);
1184       if (aWidgetValidated)
1185         anObject = aWidgetValidated->findPresentedObject(theAIS);
1186     }
1187   }
1188   return anObject;
1189 }
1190
1191 bool PartSet_Module::canBeShaded(Handle(AIS_InteractiveObject) theAIS) const
1192 {
1193   bool aCanBeShaged = true;
1194
1195   Handle(PartSet_ResultSketchPrs) aPrs = Handle(PartSet_ResultSketchPrs)::DownCast(theAIS);
1196   if (!aPrs.IsNull())
1197     aCanBeShaged = false;
1198
1199   return aCanBeShaged;
1200 }
1201
1202 void PartSet_Module::addObjectBrowserMenu(QMenu* theMenu) const
1203 {
1204   QObjectPtrList aObjects = myWorkshop->selection()->selectedObjects();
1205   int aSelected = aObjects.size();
1206   SessionPtr aMgr = ModelAPI_Session::get();
1207   QAction* aActivatePartAction = myMenuMgr->action("ACTIVATE_PART_CMD");
1208
1209   bool hasResult = false;
1210   bool hasFeature = false;
1211   bool hasParameter = false;
1212   bool hasCompositeOwner = false;
1213   bool hasResultInHistory = false;
1214   bool hasFolder = false;
1215   ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter,
1216                                   hasCompositeOwner, hasResultInHistory, hasFolder);
1217
1218   ModuleBase_Operation* aCurrentOp = myWorkshop->currentOperation();
1219   if (aSelected == 1) {
1220     ObjectPtr aObject = aObjects.first();
1221     if (aObject) {
1222       ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
1223       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
1224       bool isPart = aPart.get() ||
1225         (aFeature.get() && (aFeature->getKind() == PartSetPlugin_Part::ID()));
1226       if (isPart) {
1227         DocumentPtr aPartDoc;
1228         if (!aPart.get()) {
1229           aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aFeature->firstResult());
1230         }
1231         if (aPart.get()) // this may be null is Part feature is disabled
1232           aPartDoc = aPart->partDoc();
1233
1234         theMenu->addAction(aActivatePartAction);
1235         aActivatePartAction->setEnabled((aMgr->activeDocument() != aPartDoc));
1236
1237       } else if (aObject->document() == aMgr->activeDocument()) {
1238         if (hasParameter || hasFeature) {
1239           myMenuMgr->action("EDIT_CMD")->setEnabled(true);
1240           theMenu->addAction(myMenuMgr->action("EDIT_CMD"));
1241           if (aCurrentOp && aFeature.get()) {
1242             if (aCurrentOp->id().toStdString() == aFeature->getKind())
1243               myMenuMgr->action("EDIT_CMD")->setEnabled(false);
1244           }
1245         }
1246       }
1247     }
1248   } else {
1249     if (hasFeature) {
1250       myMenuMgr->action("EDIT_CMD")->setEnabled(aCurrentOp == 0);
1251       theMenu->addAction(myMenuMgr->action("EDIT_CMD"));
1252       theMenu->addSeparator();
1253     }
1254   }
1255   bool aNotDeactivate = (aCurrentOp == 0);
1256   if (!aNotDeactivate) {
1257     aActivatePartAction->setEnabled(false);
1258   }
1259 }
1260
1261 #define EXPAND_PARENT(OBJ) \
1262 QModelIndex aObjIndex = aDataModel->objectIndex(OBJ); \
1263 if (aObjIndex.isValid()) { \
1264   QModelIndex aParent = aObjIndex.parent(); \
1265   int aCount = aDataModel->rowCount(aParent); \
1266   if (aCount == 1) \
1267     aTreeView->setExpanded(aParent, true); \
1268 }
1269
1270
1271 void PartSet_Module::processEvent(const std::shared_ptr<Events_Message>& theMessage)
1272 {
1273   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
1274     // Do not change activation of parts if an operation active
1275     static QStringList aAllowActivationList;
1276     if (aAllowActivationList.isEmpty())
1277       aAllowActivationList <<
1278       QString(PartSetPlugin_Part::ID().c_str()) <<
1279       QString(PartSetPlugin_Duplicate::ID().c_str()) <<
1280       QString(PartSetPlugin_Remove::ID().c_str());
1281     if (myWorkshop->currentOperation() &&
1282       (!aAllowActivationList.contains(myWorkshop->currentOperation()->id())))
1283       return;
1284     XGUI_Workshop* aWorkshop = getWorkshop();
1285     XGUI_DataTree* aTreeView = aWorkshop->objectBrowser()->treeView();
1286     QLabel* aLabel = aWorkshop->objectBrowser()->activeDocLabel();
1287     QPalette aPalet = aLabel->palette();
1288
1289     SessionPtr aMgr = ModelAPI_Session::get();
1290     DocumentPtr aActiveDoc = aMgr->activeDocument();
1291     if (myActivePartIndex.isValid())
1292       aTreeView->setExpanded(myActivePartIndex, false);
1293
1294     XGUI_DataModel* aDataModel = aWorkshop->objectBrowser()->dataModel();
1295     myActivePartIndex = aDataModel->documentRootIndex(aActiveDoc, 0);
1296     bool needUpdate = false;
1297     if (myActivePartIndex.isValid()) {
1298       needUpdate = aTreeView->isExpanded(myActivePartIndex);
1299       if (!needUpdate)
1300         aTreeView->setExpanded(myActivePartIndex, true);
1301     }
1302
1303     aLabel->setPalette(aPalet);
1304     aWorkshop->updateCommandStatus();
1305
1306     // Update displayed objects in order to update active color
1307     XGUI_Displayer* aDisplayer = aWorkshop->displayer();
1308     QObjectPtrList aObjects = aDisplayer->displayedObjects();
1309     bool aHidden;
1310     foreach(ObjectPtr aObj, aObjects) {
1311       aHidden = !aObj->data() || !aObj->data()->isValid() ||
1312         aObj->isDisabled() || (!aObj->isDisplayed());
1313       if (!aHidden)
1314         aDisplayer->redisplay(aObj, false);
1315     }
1316     aDisplayer->updateViewer();
1317     // Update tree items if they are expanded
1318     if (needUpdate) {
1319       aTreeView->viewport()->repaint(aTreeView->viewport()->rect());
1320     }
1321   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
1322     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
1323         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
1324     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
1325
1326     ObjectPtr aConstrObj;
1327     ObjectPtr aResultObj;
1328     std::set<ObjectPtr>::const_iterator aIt;
1329     DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
1330     for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
1331       ObjectPtr aObject = (*aIt);
1332       if ((!aResultObj.get()) && (aObject->groupName() == ModelAPI_ResultBody::group())
1333           && (aObject->document() != aRootDoc))
1334         aResultObj = aObject;
1335       if ((!aConstrObj.get()) && (aObject->groupName() == ModelAPI_ResultConstruction::group())
1336           && (aObject->document() != aRootDoc))
1337         aConstrObj = aObject;
1338       if (aResultObj.get() && aConstrObj.get())
1339         break;
1340     }
1341
1342     if (aResultObj.get() || aConstrObj.get()) {
1343       XGUI_Workshop* aWorkshop = getWorkshop();
1344       XGUI_DataTree* aTreeView = aWorkshop->objectBrowser()->treeView();
1345       XGUI_DataModel* aDataModel = aWorkshop->objectBrowser()->dataModel();
1346
1347       if (aResultObj.get()) {
1348         EXPAND_PARENT(aResultObj)
1349       }
1350       if (aConstrObj.get()) {
1351         EXPAND_PARENT(aConstrObj)
1352       }
1353     }
1354   }
1355 }
1356
1357 void PartSet_Module::onTreeViewDoubleClick(const QModelIndex& theIndex)
1358 {
1359   if (myWorkshop->currentOperation()) // Do not change activation of parts if an operation active
1360     return;
1361   SessionPtr aMgr = ModelAPI_Session::get();
1362   if (!theIndex.isValid()) {
1363     // It seems that this code is obsolete
1364     //aMgr->setActiveDocument(aMgr->moduleDocument());
1365     return;
1366   }
1367   if (theIndex.column() != 1) // Use only first column
1368     return;
1369
1370   XGUI_Workshop* aWorkshop = getWorkshop();
1371   XGUI_DataModel* aDataModel = aWorkshop->objectBrowser()->dataModel();
1372   // De not use non editable Indexes
1373   if ((aDataModel->flags(theIndex) & Qt::ItemIsSelectable) == 0)
1374     return;
1375   ObjectPtr aObj = aDataModel->object(theIndex);
1376
1377   ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
1378   if (!aPart.get()) { // Probably this is Feature
1379     FeaturePtr aPartFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
1380     if (aPartFeature.get() && (aPartFeature->getKind() == PartSetPlugin_Part::ID())) {
1381       aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->firstResult());
1382     }
1383   }
1384   if (aPart.get()) { // if this is a part
1385     if (aPart->partDoc() == aMgr->activeDocument()) {
1386       myMenuMgr->activatePartSet();
1387     } else {
1388       myMenuMgr->activatePart(aPart);
1389     }
1390   }
1391 }
1392
1393
1394 void PartSet_Module::onViewCreated(ModuleBase_IViewWindow*)
1395 {
1396   // z layer is created for all started operations in order to visualize operation AIS presentation
1397   // over the object
1398   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
1399   if (aContext.IsNull())
1400     return;
1401
1402   Handle(V3d_Viewer) aViewer = aContext->CurrentViewer();
1403   if (myVisualLayerId == 0) {
1404     if (myVisualLayerId == 0)
1405       aViewer->AddZLayer(myVisualLayerId);
1406   } else {
1407     TColStd_SequenceOfInteger aZList;
1408     aViewer->GetAllZLayers(aZList);
1409     bool aFound = false;
1410     for (int i = 1; i <= aZList.Length(); i++) {
1411       if (aZList(i) == myVisualLayerId) {
1412         aFound = true;
1413         break;
1414       }
1415     }
1416     if (!aFound)
1417       aViewer->AddZLayer(myVisualLayerId);
1418   }
1419   // if there is an active operation with validated widget,
1420   // the filters of this widget should be activated in the created view
1421   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
1422   if (aOperation) {
1423     ModuleBase_ModelWidget* anActiveWidget = activeWidget();
1424     if (anActiveWidget) {
1425       ModuleBase_WidgetSelector* aWSelector =
1426         dynamic_cast<ModuleBase_WidgetSelector*>(anActiveWidget);
1427       if (aWSelector)
1428         aWSelector->activateSelectionAndFilters(true);
1429     }
1430   }
1431 }
1432
1433 //******************************************************
1434 void PartSet_Module::widgetStateChanged(int thePreviousState)
1435 {
1436   mySketchMgr->widgetStateChanged(thePreviousState);
1437 }
1438
1439 bool PartSet_Module::processEnter(const std::string& thePreviousAttributeID)
1440 {
1441   return mySketchReentrantMgr->processEnter(thePreviousAttributeID);
1442 }
1443
1444 //******************************************************
1445 void PartSet_Module::beforeOperationStopped(ModuleBase_Operation* theOperation)
1446 {
1447   if (PartSet_SketcherMgr::isSketchOperation(theOperation)) {
1448     mySketchMgr->stopSketch(theOperation);
1449   }
1450 }
1451
1452 //******************************************************
1453 GeomShapePtr PartSet_Module::findShape(const AttributePtr& theAttribute)
1454 {
1455   GeomShapePtr aGeomShape;
1456
1457   ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
1458   if (anOperation && sketchMgr()->isNestedSketchOperation(anOperation)) {
1459     aGeomShape = PartSet_Tools::findShapeBy2DPoint(theAttribute, myWorkshop);
1460   }
1461   return aGeomShape;
1462 }
1463
1464 //******************************************************
1465 AttributePtr PartSet_Module::findAttribute(const ObjectPtr& theObject,
1466                                            const GeomShapePtr& theGeomShape)
1467 {
1468   AttributePtr anAttribute;
1469   GeomShapePtr aGeomShape = theGeomShape;
1470   if (!aGeomShape.get()) {
1471     // processing shape of result, e.g. sketch circle center is selected, this is a result
1472     // the geom shape is empty, the shape of result should be used
1473     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
1474     if (aResult.get()) {
1475       aGeomShape = aResult->shape();
1476     }
1477   }
1478
1479   if (aGeomShape.get()) {
1480     TopoDS_Shape aTDSShape = aGeomShape->impl<TopoDS_Shape>();
1481     return PartSet_Tools::findAttributeBy2dPoint(theObject, aTDSShape,
1482                                                  mySketchMgr->activeSketch());
1483   }
1484   return anAttribute;
1485 }
1486
1487 //******************************************************
1488 std::shared_ptr<Events_Message> PartSet_Module::reentrantMessage()
1489 {
1490   return sketchReentranceMgr()->reentrantMessage();
1491 }
1492
1493 //******************************************************
1494 void PartSet_Module::setReentrantPreSelection(const std::shared_ptr<Events_Message>& theMessage)
1495 {
1496   sketchReentranceMgr()->setReentrantPreSelection(theMessage);
1497 }
1498
1499 //******************************************************
1500 void PartSet_Module::onChoiceChanged(ModuleBase_ModelWidget* theWidget,
1501                                      int theIndex)
1502 {
1503   ModuleBase_WidgetChoice* aChoiceWidget = dynamic_cast<ModuleBase_WidgetChoice*>(theWidget);
1504   if (!aChoiceWidget)
1505     return;
1506
1507   QString aChoiceTitle = aChoiceWidget->getPropertyPanelTitle(theIndex);
1508   if (!aChoiceTitle.isEmpty()) {
1509     ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
1510     if (!aOperation)
1511       return;
1512     ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
1513     if (aPanel)
1514       aPanel->setWindowTitle(aChoiceTitle);
1515   }
1516 }
1517
1518 //******************************************************
1519 XGUI_Workshop* PartSet_Module::getWorkshop() const
1520 {
1521   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
1522   return aConnector->workshop();
1523 }
1524
1525 //******************************************************
1526 void PartSet_Module::setDefaultConstraintShown()
1527 {
1528   myHasConstraintShown[PartSet_Tools::Geometrical] = true;
1529   myHasConstraintShown[PartSet_Tools::Dimensional] = true;
1530   myHasConstraintShown[PartSet_Tools::Expressions] = false;
1531 }