Salome HOME
Method isStable is defined
[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           XGUI_Displayer::DisplayMode aMode = aDisplayer->displayMode(aObject);
181           if (aMode != XGUI_Displayer::NoMode) {
182             action("WIREFRAME_CMD")->setEnabled(aMode == XGUI_Displayer::Shading);
183             action("SHADING_CMD")->setEnabled(aMode == XGUI_Displayer::Wireframe);
184           } else {
185             action("WIREFRAME_CMD")->setEnabled(true);
186             action("SHADING_CMD")->setEnabled(true);
187           }
188         }
189         if (!hasFeature) {
190           bool aHasSubResults = ModelAPI_Tools::hasSubResults(
191                                             std::dynamic_pointer_cast<ModelAPI_Result>(aObject));
192           if (aHasSubResults) {
193             action("HIDE_CMD")->setEnabled(true);
194             action("SHOW_CMD")->setEnabled(true);
195           }
196           else {
197             if (aObject->isDisplayed()) {
198               action("HIDE_CMD")->setEnabled(true);
199             } else if (hasResult && (!hasParameter)) {
200               action("SHOW_CMD")->setEnabled(true);
201             }
202           }
203           if (!(hasParameter || hasFeature))
204             action("SHOW_ONLY_CMD")->setEnabled(true);
205         }
206         else if (hasFeature && myWorkshop->canMoveFeature())
207           action("MOVE_CMD")->setEnabled(true);
208
209         if( aMgr->activeDocument() == aObject->document() )
210         {
211           action("RENAME_CMD")->setEnabled(true);
212           action("DELETE_CMD")->setEnabled(true);
213         }
214       }
215     } else {
216       // parameter is commented because the actions are not in the list of result parameter actions
217       if (hasResult /*&& (!hasParameter)*/) {
218         action("SHOW_CMD")->setEnabled(true);
219         action("HIDE_CMD")->setEnabled(true);
220         action("SHOW_ONLY_CMD")->setEnabled(true);
221         action("SHADING_CMD")->setEnabled(true);
222         action("WIREFRAME_CMD")->setEnabled(true);
223       }
224     }
225     bool allActive = true;
226     foreach( ObjectPtr aObject, aObjects )
227       if( aMgr->activeDocument() != aObject->document() )  {
228         allActive = false;
229         break;
230       }
231     if (!hasSubFeature && allActive ) {
232       if (hasFeature || hasParameter)
233         action("DELETE_CMD")->setEnabled(true);
234     }
235   }
236
237   // Show/Hide command has to be disabled for objects from non active document
238   bool aDeactivate = false;
239   foreach (ObjectPtr aObj, aObjects) {
240     if (!aObj->document()->isActive()) {
241       if ((aObj->document() != ModelAPI_Session::get()->moduleDocument()) ||
242            aObj->groupName() == ModelAPI_ResultPart::group()) {
243         aDeactivate = true;
244         break;
245       }
246     }
247   }
248   if (aDeactivate) {
249     // If at leas a one objec can not be edited then Show/Hide has to be disabled
250     action("SHOW_CMD")->setEnabled(false);
251     action("HIDE_CMD")->setEnabled(false);
252     action("SHOW_ONLY_CMD")->setEnabled(false);
253   }
254
255   if (myWorkshop->canChangeColor())
256     action("COLOR_CMD")->setEnabled(true);
257
258   ModuleBase_IModule* aModule = myWorkshop->module();
259   if (aModule)
260     aModule->updateObjectBrowserMenu(myActions);
261 }
262
263 void XGUI_ContextMenuMgr::updateViewerMenu()
264 {
265   foreach(QAction* aAction, myActions)
266     aAction->setEnabled(false);
267
268   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
269   QList<ModuleBase_ViewerPrs> aPrsList = aSelMgr->selection()->getSelected(ModuleBase_ISelection::Viewer);
270   if (aPrsList.size() > 0) {
271     bool isVisible = false;
272     bool isShading = false;
273     bool canBeShaded = false;
274     ObjectPtr aObject;
275     foreach(ModuleBase_ViewerPrs aPrs, aPrsList) {
276       aObject = aPrs.object();
277       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
278       if (aRes && aRes->isDisplayed()) {
279         isVisible = true;
280         canBeShaded = myWorkshop->displayer()->canBeShaded(aObject);
281         isShading = (myWorkshop->displayer()->displayMode(aObject) == XGUI_Displayer::Shading);      
282         break;
283       }
284     }
285     if (isVisible) {
286       if (canBeShaded) {
287         XGUI_Displayer* aDisplayer = myWorkshop->displayer();
288         XGUI_Displayer::DisplayMode aMode = aDisplayer->displayMode(aObject);
289         if (aMode != XGUI_Displayer::NoMode) {
290           action("WIREFRAME_CMD")->setEnabled(aMode == XGUI_Displayer::Shading);
291           action("SHADING_CMD")->setEnabled(aMode == XGUI_Displayer::Wireframe);
292         } else {
293           action("WIREFRAME_CMD")->setEnabled(true);
294           action("SHADING_CMD")->setEnabled(true);
295         }
296       }
297       action("SHOW_ONLY_CMD")->setEnabled(true);
298       action("HIDE_CMD")->setEnabled(true);
299     } else
300       action("SHOW_CMD")->setEnabled(true);
301   }
302   if (myWorkshop->displayer()->objectsCount() > 0)
303     action("HIDEALL_CMD")->setEnabled(true);
304   if (myWorkshop->canChangeColor())
305     action("COLOR_CMD")->setEnabled(true);
306
307   action("DELETE_CMD")->setEnabled(true);
308
309   ModuleBase_IModule* aModule = myWorkshop->module();
310   if (aModule)
311     aModule->updateViewerMenu(myActions);
312 }
313
314 void XGUI_ContextMenuMgr::connectObjectBrowser()
315 {
316   connect(myWorkshop->objectBrowser(), SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
317           SLOT(onContextMenuRequest(QContextMenuEvent*)));
318 }
319
320 void XGUI_ContextMenuMgr::connectViewer()
321 {
322   connect(myWorkshop->viewer(), SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
323           SLOT(onContextMenuRequest(QContextMenuEvent*)));
324 }
325
326
327 void XGUI_ContextMenuMgr::buildObjBrowserMenu()
328 {
329   QAction* aSeparator = new QAction(this);
330   aSeparator->setSeparator(true);
331
332   QActionsList aList;
333   
334   // Result construction menu
335   aList.append(action("SHOW_CMD"));
336   aList.append(action("HIDE_CMD"));
337   aList.append(action("SHOW_ONLY_CMD"));
338   aList.append(action("COLOR_CMD"));
339   aList.append(mySeparator);
340   aList.append(action("RENAME_CMD"));
341   myObjBrowserMenus[ModelAPI_ResultConstruction::group()] = aList;
342   //-------------------------------------
343   // Result body menu
344   aList.clear();
345   aList.append(action("WIREFRAME_CMD"));
346   aList.append(action("SHADING_CMD"));
347   aList.append(action("COLOR_CMD"));
348   aList.append(mySeparator);
349   aList.append(action("SHOW_CMD"));
350   aList.append(action("HIDE_CMD"));
351   aList.append(action("SHOW_ONLY_CMD"));
352   aList.append(mySeparator);
353   aList.append(action("RENAME_CMD"));
354   myObjBrowserMenus[ModelAPI_ResultBody::group()] = aList;
355   // Group menu
356   myObjBrowserMenus[ModelAPI_ResultGroup::group()] = aList;
357   // Result part menu
358   myObjBrowserMenus[ModelAPI_ResultPart::group()] = aList;
359   //-------------------------------------
360   // Feature menu
361   aList.clear();
362   aList.append(action("DELETE_CMD"));
363   aList.append(action("MOVE_CMD"));
364   aList.append(mySeparator);
365   aList.append(action("RENAME_CMD"));
366   myObjBrowserMenus[ModelAPI_Feature::group()] = aList;
367
368   aList.clear();
369   aList.append(action("DELETE_CMD"));
370   aList.append(mySeparator);
371   aList.append(action("RENAME_CMD"));
372   myObjBrowserMenus[ModelAPI_ResultParameter::group()] = aList;
373   //-------------------------------------
374 }
375
376 void XGUI_ContextMenuMgr::buildViewerMenu()
377 {
378   QActionsList aList;
379   // Result construction menu
380   aList.append(action("HIDE_CMD"));
381   aList.append(action("SHOW_ONLY_CMD"));
382   aList.append(action("HIDEALL_CMD"));
383   aList.append(action("COLOR_CMD"));
384   myViewerMenu[ModelAPI_ResultConstruction::group()] = aList;
385   // Result part menu
386   myViewerMenu[ModelAPI_ResultPart::group()] = aList;
387   //-------------------------------------
388   // Result body menu
389   aList.clear();
390   aList.append(action("WIREFRAME_CMD"));
391   aList.append(action("SHADING_CMD"));
392   aList.append(action("COLOR_CMD"));
393   aList.append(mySeparator);
394   aList.append(action("HIDE_CMD"));
395   aList.append(action("SHOW_ONLY_CMD"));
396   aList.append(action("HIDEALL_CMD"));
397   myViewerMenu[ModelAPI_ResultBody::group()] = aList;
398   // Group menu
399   myViewerMenu[ModelAPI_ResultGroup::group()] = aList;
400   //-------------------------------------
401
402 }
403
404
405 void XGUI_ContextMenuMgr::addObjBrowserMenu(QMenu* theMenu) const
406 {
407   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
408   QObjectPtrList aObjects = aSelMgr->selection()->selectedObjects();
409   int aSelected = aObjects.size();
410   QActionsList aActions;
411   if (aSelected == 1) {
412     ObjectPtr aObject = aObjects.first();
413     std::string aName = aObject->groupName();
414     if (myObjBrowserMenus.contains(aName))
415       aActions = myObjBrowserMenus[aName];
416   } else if (aSelected > 1) {
417       aActions.append(action("SHADING_CMD"));
418       aActions.append(action("WIREFRAME_CMD"));
419       aActions.append(mySeparator);
420       aActions.append(action("SHOW_CMD"));
421       aActions.append(action("HIDE_CMD"));
422       aActions.append(action("SHOW_ONLY_CMD"));
423       aActions.append(mySeparator);
424       aActions.append(action("DELETE_CMD"));
425       //aActions.append(action("MOVE_CMD"));
426       aActions.append(action("COLOR_CMD"));
427   }
428   theMenu->addActions(aActions);
429
430   ModuleBase_IModule* aModule = myWorkshop->module();
431   if (aModule) {
432     theMenu->addSeparator();
433     aModule->addObjectBrowserMenu(theMenu);
434   }
435   theMenu->addSeparator();
436   theMenu->addActions(myWorkshop->objectBrowser()->actions());
437 }
438
439 void XGUI_ContextMenuMgr::addViewerMenu(QMenu* theMenu) const
440 {
441   ModuleBase_IModule* aModule = myWorkshop->module();
442   if (aModule) {
443     if (aModule->addViewerMenu(theMenu, myActions))
444       theMenu->addSeparator();
445   }
446   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
447   QList<ModuleBase_ViewerPrs> aPrsList = aSelMgr->selection()->getSelected(ModuleBase_ISelection::Viewer);
448   int aSelected = aPrsList.size();
449   QActionsList aActions;
450   if (aSelected == 1) {
451     ObjectPtr aObject = aPrsList.first().object();
452     std::string aName = aObject->groupName();
453     if (myViewerMenu.contains(aName))
454       aActions = myViewerMenu[aName];
455     aActions.append(action("COLOR_CMD"));
456   } else if (aSelected > 1) {
457     aActions.append(action("HIDE_CMD"));
458     aActions.append(action("COLOR_CMD"));
459   }
460   theMenu->addActions(aActions);
461
462   if (!myWorkshop->isSalomeMode()) {
463     theMenu->addSeparator();
464     QMdiArea* aMDI = myWorkshop->mainWindow()->mdiArea();
465     if (aMDI->actions().size() > 0) {
466       QMenu* aSubMenu = theMenu->addMenu(tr("Windows"));
467       aSubMenu->addActions(aMDI->actions());
468     }
469   }
470 }
471
472 QStringList XGUI_ContextMenuMgr::actionObjectGroups(const QString& theName)
473 {
474   QStringList aGroups;
475
476   QMap<std::string, QActionsList>::const_iterator anIt = myObjBrowserMenus.begin(),
477                                                   aLast = myObjBrowserMenus.end();
478   for (; anIt != aLast; anIt++) {
479     QString aGroupName(anIt.key().c_str());
480     if (aGroups.contains(aGroupName))
481       continue;
482     QActionsList anActions = anIt.value();
483     QActionsList::const_iterator anAIt = anActions.begin(), anALast = anActions.end();
484     bool aFound = false;
485     for (; anAIt != anALast && !aFound; anAIt++)
486       aFound = (*anAIt)->data().toString() == theName;
487     if (aFound)
488       aGroups.append(aGroupName);
489   }
490   return aGroups;
491 }
492
493 void XGUI_ContextMenuMgr::onRename()
494 {
495   myWorkshop->objectBrowser()->onEditItem();
496 }