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