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