Salome HOME
Simplified calculation of fly out distance and creation of constraints limited only...
[modules/shaper.git] / src / XGUI / XGUI_ContextMenuMgr.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 #include "XGUI_ContextMenuMgr.h"
4 #include "XGUI_Workshop.h"
5 #include "XGUI_ObjectsBrowser.h"
6 #include "XGUI_SelectionMgr.h"
7 #include "XGUI_Displayer.h"
8 #include "XGUI_ViewerProxy.h"
9 #include "XGUI_Selection.h"
10 #include "XGUI_SalomeConnector.h"
11 #include "XGUI_DataModel.h"
12
13 #include <AppElements_MainWindow.h>
14
15 //#include "PartSetPlugin_Part.h"
16
17 #include <ModelAPI_Data.h>
18 #include <ModelAPI_AttributeDocRef.h>
19 #include <ModelAPI_Object.h>
20 #include <ModelAPI_Session.h>
21 #include <ModelAPI_ResultGroup.h>
22 #include <ModelAPI_ResultParameter.h>
23 #include <ModelAPI_ResultConstruction.h>
24 #include <ModelAPI_ResultBody.h>
25 #include <ModelAPI_Tools.h>
26
27 #include <ModuleBase_IModule.h>
28 #include <ModuleBase_Tools.h>
29
30 #include <QAction>
31 #include <QContextMenuEvent>
32 #include <QMenu>
33 #include <QMdiArea>
34
35
36 XGUI_ContextMenuMgr::XGUI_ContextMenuMgr(XGUI_Workshop* theParent)
37     : QObject(theParent),
38       myWorkshop(theParent),
39       mySeparator(0)
40 {
41 }
42
43 XGUI_ContextMenuMgr::~XGUI_ContextMenuMgr()
44 {
45 }
46
47 void XGUI_ContextMenuMgr::createActions()
48 {
49   QAction* aAction = new QAction(QIcon(":pictures/delete.png"), tr("Delete"), this);
50   QMainWindow* aDesktop = myWorkshop->mainWindow();
51   if (!aDesktop)
52     aDesktop = myWorkshop->salomeConnector()->desktop();
53   aDesktop->addAction(aAction);
54
55   addAction("DELETE_CMD", aAction);
56   aAction->setShortcut(Qt::Key_Delete);
57   aAction->setShortcutContext(Qt::ApplicationShortcut);
58
59   aAction = new QAction(QIcon(":pictures/rename_edit.png"), tr("Rename"), this);
60   addAction("RENAME_CMD", aAction);
61   connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRename()));
62
63   aAction = new QAction(QIcon(":pictures/move.png"), tr("Move to the end"), this);
64   addAction("MOVE_CMD", aAction);
65
66   aAction = new QAction(QIcon(":pictures/color.png"), tr("Color..."), this);
67   addAction("COLOR_CMD", aAction);
68
69   aAction = new QAction(QIcon(":pictures/eye_pencil.png"), tr("Show"), this);
70   addAction("SHOW_CMD", aAction);
71
72   aAction = new QAction(QIcon(":pictures/eye_pencil.png"), tr("Show only"), this);
73   addAction("SHOW_ONLY_CMD", aAction);
74
75   aAction = new QAction(QIcon(":pictures/eye_pencil_closed.png"), tr("Hide"), this);
76   addAction("HIDE_CMD", aAction);
77
78   aAction = new QAction(QIcon(":pictures/eye_pencil_closed.png"), tr("Hide all"), this);
79   addAction("HIDEALL_CMD", aAction);
80
81   aAction = new QAction(QIcon(":pictures/shading.png"), tr("Shading"), this);
82   addAction("SHADING_CMD", aAction);
83
84   aAction = new QAction(QIcon(":pictures/wireframe.png"), tr("Wireframe"), this);
85   addAction("WIREFRAME_CMD", aAction);
86
87   mySeparator = new QAction(this);
88   mySeparator->setSeparator(true);
89
90
91   buildObjBrowserMenu();
92   buildViewerMenu();
93 }
94
95 void XGUI_ContextMenuMgr::addAction(const QString& theId, QAction* theAction)
96 {
97   if (myActions.contains(theId))
98     qCritical("A command with Id = '%s' already defined!", qPrintable(theId));
99   theAction->setData(theId);
100   connect(theAction, SIGNAL(triggered(bool)), this, SLOT(onAction(bool)));
101   myActions[theId] = theAction;
102 }
103
104 QAction* XGUI_ContextMenuMgr::action(const QString& theId) const
105 {
106   if (myActions.contains(theId))
107     return myActions[theId];
108   return 0;
109 }
110
111 QAction* XGUI_ContextMenuMgr::actionByName(const QString& theName) const
112 {
113   foreach(QAction* eachAction, myActions) {
114     if (eachAction->text() == theName) {
115       return eachAction;
116     }
117   }
118   return NULL;
119 }
120
121 QStringList XGUI_ContextMenuMgr::actionIds() const
122 {
123   return myActions.keys();
124 }
125
126 void XGUI_ContextMenuMgr::onAction(bool isChecked)
127 {
128   QAction* aAction = static_cast<QAction*>(sender());
129   emit actionTriggered(aAction->data().toString(), isChecked);
130 }
131
132 void XGUI_ContextMenuMgr::updateCommandsStatus()
133 {
134 }
135
136 void XGUI_ContextMenuMgr::onContextMenuRequest(QContextMenuEvent* theEvent)
137 {
138   QMenu* aMenu = new QMenu();
139   if (sender() == myWorkshop->objectBrowser()) {
140     updateObjectBrowserMenu();
141     addObjBrowserMenu(aMenu);
142   } else if (sender() == myWorkshop->viewer()) {
143     updateViewerMenu();
144     addViewerMenu(aMenu);
145   }
146
147   if (aMenu && (aMenu->actions().size() > 0)) {
148     // it is possible that some objects should do something before and after the popup menu exec
149     // e.g. a sketch manager changes an internal flag on this signals in order to do not hide
150     // a created entity
151     emit beforeContextMenu();
152     aMenu->exec(theEvent->globalPos());
153     emit afterContextMenu();
154     delete aMenu;
155   }
156 }
157
158 void XGUI_ContextMenuMgr::updateObjectBrowserMenu() 
159 {
160   foreach(QAction* aAction, myActions)
161     aAction->setEnabled(false);
162
163   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
164   QObjectPtrList aObjects = aSelMgr->selection()->selectedObjects();
165   int aSelected = aObjects.size();
166   if (aSelected > 0) {
167     SessionPtr aMgr = ModelAPI_Session::get();
168     XGUI_Displayer* aDisplayer = myWorkshop->displayer();
169     bool hasResult = false;
170     bool hasFeature = false;
171     bool hasParameter = false;
172     bool hasSubFeature = false;
173     ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter, hasSubFeature);
174
175     //Process Feature
176     if (aSelected == 1) {
177       ObjectPtr aObject = aObjects.first();
178       if (aObject) {
179         if (hasResult && myWorkshop->canBeShaded(aObject)) {
180           action("WIREFRAME_CMD")->setEnabled(true);
181           action("SHADING_CMD")->setEnabled(true);
182         }
183         if (!hasFeature) {
184           bool aHasSubResults = ModelAPI_Tools::hasSubResults(
185                                             std::dynamic_pointer_cast<ModelAPI_Result>(aObject));
186           if (aHasSubResults) {
187             action("HIDE_CMD")->setEnabled(true);
188             action("SHOW_CMD")->setEnabled(true);
189           }
190           else {
191             if (aObject->isDisplayed()) {
192               action("HIDE_CMD")->setEnabled(true);
193             } else if (hasResult && (!hasParameter)) {
194               action("SHOW_CMD")->setEnabled(true);
195             }
196           }
197           if (!(hasParameter || hasFeature))
198             action("SHOW_ONLY_CMD")->setEnabled(true);
199         }
200         else if (hasFeature && myWorkshop->canMoveFeature())
201           action("MOVE_CMD")->setEnabled(true);
202
203         if( aMgr->activeDocument() == aObject->document() )
204         {
205           action("RENAME_CMD")->setEnabled(true);
206           action("DELETE_CMD")->setEnabled(true);
207         }
208       }
209     } else {
210       // parameter is commented because the actions are not in the list of result parameter actions
211       if (hasResult /*&& (!hasParameter)*/) {
212         action("SHOW_CMD")->setEnabled(true);
213         action("HIDE_CMD")->setEnabled(true);
214         action("SHOW_ONLY_CMD")->setEnabled(true);
215         action("SHADING_CMD")->setEnabled(true);
216         action("WIREFRAME_CMD")->setEnabled(true);
217       }
218     }
219     bool allActive = true;
220     foreach( ObjectPtr aObject, aObjects )
221       if( aMgr->activeDocument() != aObject->document() )  {
222         allActive = false;
223         break;
224       }
225     if (!hasSubFeature && allActive ) {
226       if (hasFeature || hasParameter)
227         action("DELETE_CMD")->setEnabled(true);
228     }
229   }
230
231   // Show/Hide command has to be disabled for objects from non active document
232   bool aDeactivate = false;
233   foreach (ObjectPtr aObj, aObjects) {
234     if (!aObj->document()->isActive()) {
235       if ((aObj->document() != ModelAPI_Session::get()->moduleDocument()) ||
236            aObj->groupName() == ModelAPI_ResultPart::group()) {
237         aDeactivate = true;
238         break;
239       }
240     }
241   }
242   if (aDeactivate) {
243     // If at leas a one objec can not be edited then Show/Hide has to be disabled
244     action("SHOW_CMD")->setEnabled(false);
245     action("HIDE_CMD")->setEnabled(false);
246     action("SHOW_ONLY_CMD")->setEnabled(false);
247   }
248
249   if (myWorkshop->canChangeColor())
250     action("COLOR_CMD")->setEnabled(true);
251
252   ModuleBase_IModule* aModule = myWorkshop->module();
253   if (aModule)
254     aModule->updateObjectBrowserMenu(myActions);
255 }
256
257 void XGUI_ContextMenuMgr::updateViewerMenu()
258 {
259   foreach(QAction* aAction, myActions)
260     aAction->setEnabled(false);
261
262   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
263   QList<ModuleBase_ViewerPrs> aPrsList = aSelMgr->selection()->getSelected(ModuleBase_ISelection::Viewer);
264   if (aPrsList.size() > 0) {
265     bool isVisible = false;
266     bool isShading = false;
267     bool canBeShaded = false;
268     ObjectPtr aObject;
269     foreach(ModuleBase_ViewerPrs aPrs, aPrsList) {
270       aObject = aPrs.object();
271       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
272       if (aRes && aRes->isDisplayed()) {
273         isVisible = true;
274         canBeShaded = myWorkshop->displayer()->canBeShaded(aObject);
275         isShading = (myWorkshop->displayer()->displayMode(aObject) == XGUI_Displayer::Shading);      
276         break;
277       }
278     }
279     if (isVisible) {
280       if (canBeShaded) {
281         action("WIREFRAME_CMD")->setEnabled(true);
282         action("SHADING_CMD")->setEnabled(true);
283       }
284       action("SHOW_ONLY_CMD")->setEnabled(true);
285       action("HIDE_CMD")->setEnabled(true);
286     } else
287       action("SHOW_CMD")->setEnabled(true);
288   }
289   if (myWorkshop->displayer()->objectsCount() > 0)
290     action("HIDEALL_CMD")->setEnabled(true);
291   if (myWorkshop->canChangeColor())
292     action("COLOR_CMD")->setEnabled(true);
293
294   action("DELETE_CMD")->setEnabled(true);
295
296   ModuleBase_IModule* aModule = myWorkshop->module();
297   if (aModule)
298     aModule->updateViewerMenu(myActions);
299 }
300
301 void XGUI_ContextMenuMgr::connectObjectBrowser()
302 {
303   connect(myWorkshop->objectBrowser(), SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
304           SLOT(onContextMenuRequest(QContextMenuEvent*)));
305 }
306
307 void XGUI_ContextMenuMgr::connectViewer()
308 {
309   connect(myWorkshop->viewer(), SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
310           SLOT(onContextMenuRequest(QContextMenuEvent*)));
311 }
312
313
314 void XGUI_ContextMenuMgr::buildObjBrowserMenu()
315 {
316   QAction* aSeparator = new QAction(this);
317   aSeparator->setSeparator(true);
318
319   QActionsList aList;
320   
321   // Result construction menu
322   aList.append(action("SHOW_CMD"));
323   aList.append(action("HIDE_CMD"));
324   aList.append(action("SHOW_ONLY_CMD"));
325   aList.append(action("COLOR_CMD"));
326   aList.append(mySeparator);
327   aList.append(action("RENAME_CMD"));
328   myObjBrowserMenus[ModelAPI_ResultConstruction::group()] = aList;
329   //-------------------------------------
330   // Result body menu
331   aList.clear();
332   aList.append(action("WIREFRAME_CMD"));
333   aList.append(action("SHADING_CMD"));
334   aList.append(action("COLOR_CMD"));
335   aList.append(mySeparator);
336   aList.append(action("SHOW_CMD"));
337   aList.append(action("HIDE_CMD"));
338   aList.append(action("SHOW_ONLY_CMD"));
339   aList.append(mySeparator);
340   aList.append(action("RENAME_CMD"));
341   myObjBrowserMenus[ModelAPI_ResultBody::group()] = aList;
342   // Group menu
343   myObjBrowserMenus[ModelAPI_ResultGroup::group()] = aList;
344   // Result part menu
345   myObjBrowserMenus[ModelAPI_ResultPart::group()] = aList;
346   //-------------------------------------
347   // Feature menu
348   aList.clear();
349   aList.append(action("DELETE_CMD"));
350   aList.append(action("MOVE_CMD"));
351   aList.append(mySeparator);
352   aList.append(action("RENAME_CMD"));
353   myObjBrowserMenus[ModelAPI_Feature::group()] = aList;
354
355   aList.clear();
356   aList.append(action("DELETE_CMD"));
357   aList.append(mySeparator);
358   aList.append(action("RENAME_CMD"));
359   myObjBrowserMenus[ModelAPI_ResultParameter::group()] = aList;
360   //-------------------------------------
361 }
362
363 void XGUI_ContextMenuMgr::buildViewerMenu()
364 {
365   QActionsList aList;
366   // Result construction menu
367   aList.append(action("HIDE_CMD"));
368   aList.append(action("SHOW_ONLY_CMD"));
369   aList.append(action("HIDEALL_CMD"));
370   aList.append(action("COLOR_CMD"));
371   myViewerMenu[ModelAPI_ResultConstruction::group()] = aList;
372   // Result part menu
373   myViewerMenu[ModelAPI_ResultPart::group()] = aList;
374   //-------------------------------------
375   // Result body menu
376   aList.clear();
377   aList.append(action("WIREFRAME_CMD"));
378   aList.append(action("SHADING_CMD"));
379   aList.append(action("COLOR_CMD"));
380   aList.append(mySeparator);
381   aList.append(action("HIDE_CMD"));
382   aList.append(action("SHOW_ONLY_CMD"));
383   aList.append(action("HIDEALL_CMD"));
384   myViewerMenu[ModelAPI_ResultBody::group()] = aList;
385   // Group menu
386   myViewerMenu[ModelAPI_ResultGroup::group()] = aList;
387   //-------------------------------------
388
389 }
390
391
392 void XGUI_ContextMenuMgr::addObjBrowserMenu(QMenu* theMenu) const
393 {
394   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
395   QObjectPtrList aObjects = aSelMgr->selection()->selectedObjects();
396   int aSelected = aObjects.size();
397   QActionsList aActions;
398   if (aSelected == 1) {
399     ObjectPtr aObject = aObjects.first();
400     std::string aName = aObject->groupName();
401     if (myObjBrowserMenus.contains(aName))
402       aActions = myObjBrowserMenus[aName];
403   } else if (aSelected > 1) {
404       aActions.append(action("SHADING_CMD"));
405       aActions.append(action("WIREFRAME_CMD"));
406       aActions.append(mySeparator);
407       aActions.append(action("SHOW_CMD"));
408       aActions.append(action("HIDE_CMD"));
409       aActions.append(action("SHOW_ONLY_CMD"));
410       aActions.append(mySeparator);
411       aActions.append(action("DELETE_CMD"));
412       //aActions.append(action("MOVE_CMD"));
413   }
414   theMenu->addActions(aActions);
415
416   ModuleBase_IModule* aModule = myWorkshop->module();
417   if (aModule) {
418     theMenu->addSeparator();
419     aModule->addObjectBrowserMenu(theMenu);
420   }
421   theMenu->addSeparator();
422   theMenu->addActions(myWorkshop->objectBrowser()->actions());
423 }
424
425 void XGUI_ContextMenuMgr::addViewerMenu(QMenu* theMenu) const
426 {
427   ModuleBase_IModule* aModule = myWorkshop->module();
428   if (aModule) {
429     if (aModule->addViewerMenu(theMenu, myActions))
430       theMenu->addSeparator();
431   }
432   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
433   QList<ModuleBase_ViewerPrs> aPrsList = aSelMgr->selection()->getSelected(ModuleBase_ISelection::Viewer);
434   int aSelected = aPrsList.size();
435   QActionsList aActions;
436   if (aSelected == 1) {
437     ObjectPtr aObject = aPrsList.first().object();
438     std::string aName = aObject->groupName();
439     if (myViewerMenu.contains(aName))
440       aActions = myViewerMenu[aName];
441   } else if (aSelected > 1) {
442     aActions.append(action("HIDE_CMD"));
443   }
444   theMenu->addActions(aActions);
445
446   if (!myWorkshop->isSalomeMode()) {
447     theMenu->addSeparator();
448     QMdiArea* aMDI = myWorkshop->mainWindow()->mdiArea();
449     if (aMDI->actions().size() > 0) {
450       QMenu* aSubMenu = theMenu->addMenu(tr("Windows"));
451       aSubMenu->addActions(aMDI->actions());
452     }
453   }
454 }
455
456 QStringList XGUI_ContextMenuMgr::actionObjectGroups(const QString& theName)
457 {
458   QStringList aGroups;
459
460   QMap<std::string, QActionsList>::const_iterator anIt = myObjBrowserMenus.begin(),
461                                                   aLast = myObjBrowserMenus.end();
462   for (; anIt != aLast; anIt++) {
463     QString aGroupName(anIt.key().c_str());
464     if (aGroups.contains(aGroupName))
465       continue;
466     QActionsList anActions = anIt.value();
467     QActionsList::const_iterator anAIt = anActions.begin(), anALast = anActions.end();
468     bool aFound = false;
469     for (; anAIt != anALast && !aFound; anAIt++)
470       aFound = (*anAIt)->data().toString() == theName;
471     if (aFound)
472       aGroups.append(aGroupName);
473   }
474   return aGroups;
475 }
476
477 void XGUI_ContextMenuMgr::onRename()
478 {
479   myWorkshop->objectBrowser()->onEditItem();
480 }