]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_MenuMgr.cpp
Salome HOME
Issue #2440 Can't validate coincidence between a line and an imported line
[modules/shaper.git] / src / PartSet / PartSet_MenuMgr.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_MenuMgr.h"
22 #include "PartSet_Module.h"
23 #include "PartSet_SketcherMgr.h"
24 #include "PartSet_Tools.h"
25
26 #include <PartSetPlugin_Part.h>
27
28 #include <GeomAPI_Pnt2d.h>
29 #include <GeomDataAPI_Point2D.h>
30
31 #include <SketchPlugin_ConstraintCoincidence.h>
32 #include <SketchPlugin_Line.h>
33 #include <SketchPlugin_Circle.h>
34 #include <SketchPlugin_Point.h>
35 #include <SketchPlugin_Sketch.h>
36
37 #include <ModuleBase_ISelection.h>
38 #include <ModuleBase_Operation.h>
39 #include <ModuleBase_OperationAction.h>
40 #include <ModuleBase_OperationFeature.h>
41 #include <ModuleBase_ViewerPrs.h>
42 #include <ModuleBase_Tools.h>
43
44 #include <XGUI_ModuleConnector.h>
45 #include <XGUI_Workshop.h>
46 #include <XGUI_Displayer.h>
47 #include <XGUI_DataModel.h>
48 #include <XGUI_OperationMgr.h>
49 #include <XGUI_ObjectsBrowser.h>
50
51 #include <Events_Loop.h>
52 #include <ModelAPI_Events.h>
53 #include <ModelAPI_Session.h>
54 #include <ModelAPI_ResultParameter.h>
55
56 #include <QMainWindow>
57 #include <QAction>
58 #include <QMenu>
59 #include <QEvent>
60
61 #include <TopoDS.hxx>
62 #include <BRep_Tool.hxx>
63
64 PartSet_MenuMgr::PartSet_MenuMgr(PartSet_Module* theModule)
65   : QObject(theModule), myModule(theModule), myPrevId(-1)
66 {
67   createActions();
68 }
69
70
71 QAction* PartSet_MenuMgr::action(const QString& theId) const
72 {
73   if (myActions.contains(theId))
74     return myActions[theId];
75   return 0;
76 }
77
78 void PartSet_MenuMgr::addAction(const QString& theId, QAction* theAction)
79 {
80   if (myActions.contains(theId))
81     qCritical("A command with Id = '%s' already defined!", qPrintable(theId));
82   theAction->setData(theId);
83   connect(theAction, SIGNAL(triggered(bool)), this, SLOT(onAction(bool)));
84   myActions[theId] = theAction;
85 }
86
87 void PartSet_MenuMgr::createActions()
88 {
89   QAction* aAction;
90
91   QWidget* aParent = myModule->workshop()->desktop();
92   aAction = ModuleBase_Tools::createAction(QIcon(), tr("Auxiliary"), aParent);
93   aAction->setCheckable(true);
94   addAction("AUXILIARY_CMD", aAction);
95
96   aAction = ModuleBase_Tools::createAction(QIcon(":icons/activate.png"), tr("Activate"), aParent,
97                                            this, SLOT(onActivatePart(bool)));
98   myActions["ACTIVATE_PART_CMD"] = aAction;
99
100   // Activate PartSet
101   aAction = ModuleBase_Tools::createAction(QIcon(":icons/activate.png"), tr("Activate"), aParent,
102                         this, SLOT(onActivatePartSet(bool)));
103   myActions["ACTIVATE_PARTSET_CMD"] = aAction;
104
105   aAction = ModuleBase_Tools::createAction(QIcon(":icons/edit.png"), tr("Edit..."), aParent,
106                          this, SLOT(onEdit(bool)));
107   myActions["EDIT_CMD"] = aAction;
108 }
109
110
111 void PartSet_MenuMgr::onAction(bool isChecked)
112 {
113   QAction* aAction = static_cast<QAction*>(sender());
114   QString anId = aAction->data().toString();
115
116   if (anId == "AUXILIARY_CMD") {
117     setAuxiliary(isChecked);
118   }
119 }
120
121 bool PartSet_MenuMgr::addViewerMenu(const QMap<QString, QAction*>& theStdActions,
122                                     QWidget* theParent,
123                                     QMap<int, QAction*>& theMenuActions) const
124 {
125   int anIndex = 0;
126
127   ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
128   if (!PartSet_SketcherMgr::isSketchOperation(anOperation) &&
129       !myModule->sketchMgr()->isNestedSketchOperation(anOperation))
130     return false;
131
132   myCoinsideLines.clear();
133   ModuleBase_ISelection* aSelection = myModule->workshop()->selection();
134
135   bool aIsDetach = false;
136   bool hasAttribute = false;
137   bool hasFeature = false;
138
139   QList<ModuleBase_ViewerPrsPtr> aPrsList = aSelection->getSelected(ModuleBase_ISelection::Viewer);
140   if (aPrsList.size() > 1) {
141     hasFeature = true;
142   } else if (aPrsList.size() == 1) {
143     ResultPtr aResult;
144     FeaturePtr aFeature;
145     foreach(ModuleBase_ViewerPrsPtr aPrs, aPrsList) {
146       aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aPrs->object());
147       if (aResult.get() != NULL) {
148         const GeomShapePtr& aShape = aPrs->shape();
149         if (aShape.get() && aShape->isEqual(aResult->shape()))
150           hasFeature = true;
151         else
152           hasAttribute = true;
153       } else {
154         aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aPrs->object());
155         hasFeature = (aFeature.get() != NULL);
156       }
157     }
158
159     const GeomShapePtr& aShape = aPrsList.first()->shape();
160     if (aShape.get() && !aShape->isNull() && aShape->shapeType() == GeomAPI_Shape::VERTEX) {
161       // Find 2d coordinates
162       FeaturePtr aSketchFea = myModule->sketchMgr()->activeSketch();
163       if (aSketchFea->getKind() == SketchPlugin_Sketch::ID()) {
164         const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
165         gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aTDShape));
166         std::shared_ptr<GeomAPI_Pnt> aPnt3d(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z()));
167         std::shared_ptr<GeomAPI_Pnt2d> aSelPnt = PartSet_Tools::convertTo2D(aSketchFea, aPnt3d);
168
169         // Find coincident in these coordinates
170         ObjectPtr aObj = aPrsList.first()->object();
171         FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
172         FeaturePtr aCoincident = PartSet_Tools::findFirstCoincidence(aFeature, aSelPnt);
173         // If we have coincidence then add Detach menu
174         if (aCoincident.get() != NULL) {
175           QList<FeaturePtr> aCoins;
176           mySelectedFeature = aCoincident;
177           QList<bool> anIsAttributes;
178           PartSet_Tools::findCoincidences(mySelectedFeature, myCoinsideLines, aCoins,
179                                           SketchPlugin_ConstraintCoincidence::ENTITY_A(),
180                                           anIsAttributes);
181           PartSet_Tools::findCoincidences(mySelectedFeature, myCoinsideLines, aCoins,
182                                           SketchPlugin_ConstraintCoincidence::ENTITY_B(),
183                                           anIsAttributes);
184           if (myCoinsideLines.size() > 0) {
185             aIsDetach = true;
186             QMenu* aSubMenu = new QMenu(tr("Detach"), theParent);
187             theMenuActions[anIndex++] = aSubMenu->menuAction();
188             QAction* aAction;
189             int i = 0;
190             foreach (FeaturePtr aCoins, myCoinsideLines) {
191               QString anItemText = aCoins->data()->name().c_str();
192 #ifdef _DEBUG
193               if (anIsAttributes[i])
194                 anItemText += " [attribute]";
195 #endif
196               aAction = aSubMenu->addAction(anItemText);
197               aAction->setData(QVariant(i));
198               i++;
199             }
200             connect(aSubMenu, SIGNAL(hovered(QAction*)), SLOT(onLineHighlighted(QAction*)));
201             connect(aSubMenu, SIGNAL(aboutToHide()), SLOT(onDetachMenuHide()));
202             connect(aSubMenu, SIGNAL(triggered(QAction*)), SLOT(onLineDetach(QAction*)));
203           }
204         }
205       }
206     }
207   }
208   if (!hasAttribute) {
209     bool isAuxiliary;
210     if (canSetAuxiliary(isAuxiliary)) {
211       QAction* anAction = action("AUXILIARY_CMD");
212       theMenuActions[anIndex++] = anAction;
213       anAction->setChecked(isAuxiliary);
214     }
215   }
216
217   if (!aIsDetach && hasFeature) {
218     // Delete item should be the last in the list of actions
219     theMenuActions[1000] = theStdActions["DELETE_CMD"];
220   }
221
222   return true;
223 }
224
225 void PartSet_MenuMgr::updateViewerMenu(const QMap<QString, QAction*>& theStdActions)
226 {
227   ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
228
229   bool isActiveSketch = PartSet_SketcherMgr::isSketchOperation(anOperation) ||
230                         myModule->sketchMgr()->isNestedSketchOperation(anOperation);
231   if (isActiveSketch) {
232     theStdActions["WIREFRAME_CMD"]->setEnabled(false);
233     theStdActions["SHADING_CMD"]->setEnabled(false);
234     theStdActions["SHOW_ONLY_CMD"]->setEnabled(false);
235     theStdActions["SHOW_CMD"]->setEnabled(false);
236     theStdActions["HIDE_CMD"]->setEnabled(false);
237     theStdActions["HIDEALL_CMD"]->setEnabled(false);
238   }
239 }
240
241
242 void PartSet_MenuMgr::onLineHighlighted(QAction* theAction)
243 {
244   if (myPrevId != -1) {
245     // Restore color for previous object
246     setLineColor(myPrevId, myColor, false);
247   }
248   myPrevId = theAction->data().toInt();
249   myColor = setLineColor(myPrevId, Qt::white, true);
250 }
251
252 QColor PartSet_MenuMgr::setLineColor(int theId, const QColor theColor, bool theUpdate)
253 {
254   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
255   XGUI_Workshop* aWorkshop = aConnector->workshop();
256   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
257
258   FeaturePtr aLine = myCoinsideLines.at(myPrevId);
259   std::list<ResultPtr>::const_iterator aIt;
260   const std::list<ResultPtr>& aResults = aLine->results();
261   QColor aColor;
262   for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
263     aColor = aDisplayer->setObjectColor((*aIt), theColor, false);
264   }
265   if (theUpdate)
266     aDisplayer->updateViewer();
267   return aColor;
268 }
269
270
271 void addRefCoincidentFeatures(const std::set<AttributePtr>& theRefList,
272   std::shared_ptr<GeomAPI_Pnt2d>& theRefPnt,
273   QObjectPtrList& theOutList)
274 {
275   std::set<AttributePtr>::const_iterator aIt;
276   for (aIt = theRefList.cbegin(); aIt != theRefList.cend(); ++aIt) {
277     std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
278     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
279     if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
280       std::shared_ptr<GeomAPI_Pnt2d> aPnt = PartSet_Tools::getCoincedencePoint(aConstrFeature);
281       if (aPnt.get() == NULL)
282         return;
283       gp_Pnt aP = aPnt->impl<gp_Pnt>();
284       if (theRefPnt->isEqual(aPnt) && (!theOutList.contains(aConstrFeature))) {
285         theOutList.append(aConstrFeature);
286       }
287     }
288   }
289 }
290
291 void PartSet_MenuMgr::onLineDetach(QAction* theAction)
292 {
293   int aId = theAction->data().toInt();
294   FeaturePtr aLine = myCoinsideLines.at(aId);
295   std::shared_ptr<GeomAPI_Pnt2d> aOrig = PartSet_Tools::getCoincedencePoint(mySelectedFeature);
296   if (!aOrig.get())
297     return;
298
299   const std::set<AttributePtr>& aRefsList = aLine->data()->refsToMe();
300
301   QObjectPtrList aToDelFeatures;
302
303   addRefCoincidentFeatures(aRefsList, aOrig, aToDelFeatures);
304
305   const std::list<ResultPtr>& aResults = aLine->results();
306   std::list<ResultPtr>::const_iterator aResIt;
307   for (aResIt = aResults.cbegin(); aResIt != aResults.cend(); aResIt++) {
308     ResultPtr aResult = (*aResIt);
309     const std::set<AttributePtr>& aRefList = aResult->data()->refsToMe();
310     addRefCoincidentFeatures(aRefList, aOrig, aToDelFeatures);
311   }
312   if (aToDelFeatures.size() > 0) {
313     XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
314     XGUI_Workshop* aWorkshop = aConnector->workshop();
315     ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
316
317     ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(
318                                    tr("Detach %1").arg(aLine->data()->name().c_str()), myModule);
319     bool isSketchOp = PartSet_SketcherMgr::isSketchOperation(anOperation);
320     XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr();
321     // the active nested sketch operation should be aborted unconditionally
322     // the Delete action should be additionally granted for the Sketch operation
323     // in order to do not abort/commit it
324     bool isCommitted;
325     if (!anOpMgr->canStartOperation(tr("Detach"), isCommitted))
326       return; // the objects are processed but can not be deleted
327
328     anOpMgr->startOperation(anOpAction);
329     aWorkshop->deleteFeatures(aToDelFeatures);
330
331     anOpMgr->commitOperation();
332   }
333   myCoinsideLines.clear();
334 }
335
336
337 void PartSet_MenuMgr::onDetachMenuHide()
338 {
339   if (myPrevId != -1) {
340     // Restore color for previous object
341     setLineColor(myPrevId, myColor, false);
342   }
343   // Clear previous definitions
344   myPrevId = -1;
345 }
346
347
348 void PartSet_MenuMgr::setAuxiliary(const bool isChecked)
349 {
350   ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
351
352   CompositeFeaturePtr aSketch = myModule->sketchMgr()->activeSketch();
353   bool isActiveSketch = PartSet_SketcherMgr::isSketchOperation(anOperation) ||
354                         myModule->sketchMgr()->isNestedSketchOperation(anOperation);
355   if (!isActiveSketch)
356     return;
357
358   QObjectPtrList anObjects;
359   bool isUseTransaction = false;
360   // 1. change auxiliary type of a created feature
361   if (myModule->sketchMgr()->isNestedCreateOperation(anOperation, aSketch) &&
362       PartSet_SketcherMgr::isEntity(anOperation->id().toStdString()) ) {
363       ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
364                                                                (anOperation);
365       if (aFOperation)
366         anObjects.append(aFOperation->feature());
367   }
368   else {
369     isUseTransaction = true;
370     // 2. change auxiliary type of selected sketch entities
371     ModuleBase_ISelection* aSelection = myModule->workshop()->selection();
372     anObjects = aSelection->selectedPresentations();
373   }
374
375   QAction* anAction = action("AUXILIARY_CMD");
376   //SessionPtr aMgr = ModelAPI_Session::get();
377   ModuleBase_OperationAction* anOpAction = 0;
378   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
379   XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr();
380   if (isUseTransaction) {
381     anOpAction = new ModuleBase_OperationAction(anAction->text(), myModule);
382     bool isSketchOp = PartSet_SketcherMgr::isSketchOperation(anOperation);
383
384     bool isCommitted;
385     if (!anOpMgr->canStartOperation(anOpAction->id(), isCommitted))
386       return; // the objects are processed but can not be deleted
387
388     anOpMgr->startOperation(anOpAction);
389   }
390   if (anObjects.size() > 0) {
391     QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
392     for (; anIt != aLast; anIt++) {
393       FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
394       if (aFeature.get() != NULL) {
395         std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
396                             std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
397         if (aSketchFeature.get() != NULL) {
398           std::string anAttribute = SketchPlugin_SketchEntity::AUXILIARY_ID();
399
400           std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
401             std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
402             aSketchFeature->data()->attribute(anAttribute));
403           if (anAuxiliaryAttr)
404             anAuxiliaryAttr->setValue(isChecked);
405         }
406       }
407     }
408   }
409   if (isUseTransaction)
410     anOpMgr->commitOperation();
411
412   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
413 }
414
415 bool PartSet_MenuMgr::canSetAuxiliary(bool& theValue) const
416 {
417   bool anEnabled = false;
418   ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
419
420   CompositeFeaturePtr aSketch = myModule->sketchMgr()->activeSketch();
421   bool isActiveSketch = PartSet_SketcherMgr::isSketchOperation(anOperation) ||
422                         myModule->sketchMgr()->isNestedSketchOperation(anOperation);
423   if (!isActiveSketch)
424     return anEnabled;
425
426   QObjectPtrList anObjects;
427   // 1. change auxiliary type of a created feature
428   if (myModule->sketchMgr()->isNestedCreateOperation(anOperation, aSketch) &&
429     PartSet_SketcherMgr::isEntity(anOperation->id().toStdString()) ) {
430     ModuleBase_OperationFeature* aFOperation =
431       dynamic_cast<ModuleBase_OperationFeature*>(anOperation);
432     if (aFOperation)
433       anObjects.append(aFOperation->feature());
434   }
435   else {
436     /// The operation should not be aborted here, because the method does not changed
437     /// the auxilliary state, but checks the possibility to perform this
438     ///if (myModule->sketchMgr()->isNestedSketchOperation(anOperation))
439     ///  anOperation->abort();
440     // 2. change auxiliary type of selected sketch entities
441     ModuleBase_ISelection* aSelection = myModule->workshop()->selection();
442     anObjects = aSelection->selectedPresentations();
443   }
444
445   bool isNotAuxiliaryFound = false;
446   if (anObjects.size() > 0) {
447     QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
448     for (; anIt != aLast && !isNotAuxiliaryFound; anIt++) {
449       FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
450       if ((aFeature.get() != NULL) && PartSet_SketcherMgr::isEntity(aFeature->getKind())) {
451         anEnabled = true;
452         std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
453                             std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
454         if (aSketchFeature.get() != NULL) {
455           std::string anAttribute = SketchPlugin_SketchEntity::AUXILIARY_ID();
456
457           std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
458             std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
459             aSketchFeature->data()->attribute(anAttribute));
460           if (anAuxiliaryAttr)
461             isNotAuxiliaryFound = !anAuxiliaryAttr->value();
462         }
463       }
464     }
465   }
466   theValue = anObjects.size() && !isNotAuxiliaryFound;
467   return anEnabled;
468 }
469
470 void PartSet_MenuMgr::onActivatePart(bool)
471 {
472   if (myModule->workshop()->currentOperation())
473     return;
474   QObjectPtrList aObjects = myModule->workshop()->selection()->selectedObjects();
475   if (aObjects.size() > 0) {
476     ObjectPtr aObj = aObjects.first();
477     ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
478     if (!aPart.get()) {
479       FeaturePtr aPartFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
480       if (aPartFeature.get() && (aPartFeature->getKind() == PartSetPlugin_Part::ID())) {
481         aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->firstResult());
482       }
483     }
484     if (aPart.get()) {
485       activatePart(aPart);
486       myModule->workshop()->updateCommandStatus();
487     }
488   }
489 }
490
491 void PartSet_MenuMgr::activatePart(ResultPartPtr thePart) const
492 {
493   bool isFirstLoad = !thePart->partDoc().get();
494   thePart->activate();
495   if (isFirstLoad) {
496     XGUI_Workshop* aWorkshop = myModule->getWorkshop();
497     XGUI_ObjectsBrowser* aObjBrowser = aWorkshop->objectBrowser();
498     DocumentPtr aDoc = thePart->partDoc();
499     std::list<bool> aStates;
500     aDoc->restoreNodesState(aStates);
501     aObjBrowser->setStateForDoc(aDoc, aStates);
502   }
503 }
504
505 void PartSet_MenuMgr::onActivatePartSet(bool)
506 {
507   if (myModule->workshop()->currentOperation())
508     return;
509   activatePartSet();
510 }
511
512 void PartSet_MenuMgr::activatePartSet() const
513 {
514   SessionPtr aMgr = ModelAPI_Session::get();
515   bool isNewTransaction = !aMgr->isOperation();
516   // activation may cause changes in current features in document, so it must be in transaction
517   if (isNewTransaction)
518     aMgr->startOperation("Activation");
519   aMgr->setActiveDocument(aMgr->moduleDocument());
520   if (isNewTransaction) aMgr->finishOperation();
521
522   myModule->workshop()->updateCommandStatus();
523 }
524
525 void PartSet_MenuMgr::grantedOperationIds(ModuleBase_Operation* theOperation,
526                                           QStringList& theIds) const
527 {
528   if (PartSet_SketcherMgr::isSketchOperation(theOperation)) {
529     theIds.append(tr("Detach"));
530     theIds.append(tr("Auxiliary"));
531   }
532 }
533
534 void PartSet_MenuMgr::onEdit(bool)
535 {
536   QObjectPtrList aObjects = myModule->workshop()->selection()->selectedObjects();
537   FeaturePtr aFeature;
538   foreach(ObjectPtr aObj, aObjects) {
539     aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
540     if (aFeature.get())
541       break;
542   }
543   if (aFeature.get() == NULL) {
544     ResultParameterPtr aParam;
545     foreach(ObjectPtr aObj, aObjects) {
546       aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObj);
547       if (aParam.get())
548         break;
549     }
550     if (aParam.get() != NULL)
551       aFeature = ModelAPI_Feature::feature(aParam);
552   }
553   if (aFeature.get() != NULL)
554     myModule->editFeature(aFeature);
555 }
556
557 bool PartSet_MenuMgr::eventFilter(QObject* theObj, QEvent* theEvent)
558 {
559   if (theEvent->type() == QEvent::MouseButtonDblClick) {
560     SessionPtr aMgr = ModelAPI_Session::get();
561     if (aMgr->activeDocument() != aMgr->moduleDocument())
562       activatePartSet();
563   }
564   return QObject::eventFilter(theObj, theEvent);
565 }