Salome HOME
CEA : Lot 2 - Auto Color for Groups
[modules/shaper.git] / src / XGUI / XGUI_ContextMenuMgr.cpp
1 // Copyright (C) 2014-2021  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include "XGUI_ContextMenuMgr.h"
21 #include "XGUI_Workshop.h"
22 #include "XGUI_ObjectsBrowser.h"
23 #include "XGUI_SelectionMgr.h"
24 #include "XGUI_Displayer.h"
25 #include "XGUI_ViewerProxy.h"
26 #include "XGUI_SalomeConnector.h"
27 #include "XGUI_Selection.h"
28 #include "XGUI_SelectionActivate.h"
29 #include "XGUI_DataModel.h"
30 #include "XGUI_OperationMgr.h"
31 #include "XGUI_Tools.h"
32 #include "XGUI_ActionsMgr.h"
33
34 #ifndef HAVE_SALOME
35 #include <AppElements_MainWindow.h>
36 #endif
37
38 //#include "PartSetPlugin_Part.h"
39
40 #include <ModelAPI_Data.h>
41 #include <ModelAPI_AttributeDocRef.h>
42 #include <ModelAPI_Object.h>
43 #include <ModelAPI_Session.h>
44 #include <ModelAPI_ResultGroup.h>
45 #include <ModelAPI_ResultParameter.h>
46 #include <ModelAPI_ResultConstruction.h>
47 #include <ModelAPI_ResultBody.h>
48 #include <ModelAPI_Tools.h>
49 #include <ModelAPI_ResultField.h>
50 #include <ModelAPI_Folder.h>
51 #include <ModelAPI_AttributeReference.h>
52 #include <ModelAPI_ResultField.h>
53
54 #include <Config_DataModelReader.h>
55
56 #include <ModuleBase_IModule.h>
57 #include <ModuleBase_Tools.h>
58 #include <ModuleBase_Operation.h>
59 #include <ModuleBase_ViewerPrs.h>
60
61 #include <QAction>
62 #include <QActionGroup>
63 #include <QContextMenuEvent>
64 #include <QMenu>
65 #include <QMdiArea>
66 #include <QMainWindow>
67 #include <QModelIndex>
68
69 XGUI_ContextMenuMgr::XGUI_ContextMenuMgr(XGUI_Workshop* theParent)
70     : QObject(theParent),
71       myWorkshop(theParent),
72       mySeparator1(0), mySeparator2(0), mySeparator3(0)
73 {
74 }
75
76 XGUI_ContextMenuMgr::~XGUI_ContextMenuMgr()
77 {
78 }
79
80 void XGUI_ContextMenuMgr::createActions()
81 {
82 #ifdef HAVE_SALOME
83   QMainWindow* aDesktop = myWorkshop->salomeConnector()->desktop();
84 #else
85   QMainWindow* aDesktop = myWorkshop->mainWindow();
86 #endif
87
88   QAction* anAction = ModuleBase_Tools::createAction(QIcon(":pictures/delete.png"), tr("Delete"),
89                                                     aDesktop);
90   aDesktop->addAction(anAction);
91
92   addAction("DELETE_CMD", anAction);
93   anAction->setShortcutContext(Qt::ApplicationShortcut);
94
95   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/rename_edit.png"), tr("Rename"),
96                                            aDesktop, this, SLOT(onRename()));
97   anAction->setShortcut(Qt::Key_F2);
98   addAction("RENAME_CMD", anAction);
99
100 #ifdef HAVE_SALOME
101   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_to_end.png"),
102                                            XGUI_Workshop::MOVE_TO_END_COMMAND, this);
103   addAction("MOVE_CMD", anAction);
104
105   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_to_end_split.png"),
106     XGUI_Workshop::MOVE_TO_END_SPLIT_COMMAND, this);
107   addAction("MOVE_SPLIT_CMD", anAction);
108 #endif
109
110   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/clean_history.png"),
111                                            tr("Clean history"), aDesktop);
112   addAction("CLEAN_HISTORY_CMD", anAction);
113
114   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/color.png"), tr("Color..."), aDesktop);
115   addAction("COLOR_CMD", anAction);
116
117   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/autocolor.png"), tr("Auto color"), aDesktop);
118   addAction("AUTOCOLOR_CMD", anAction);
119
120   anAction = ModuleBase_Tools::createAction(QIcon(""), tr("Deflection..."), aDesktop);
121   addAction("DEFLECTION_CMD", anAction);
122
123   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/transparency.png"),
124                                            tr("Transparency..."), aDesktop);
125   addAction("TRANSPARENCY_CMD", anAction);
126
127   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/eye_pencil.png"), tr("Show"), aDesktop);
128   addAction("SHOW_CMD", anAction);
129
130   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/eye_pencil.png"), tr("Show only"),
131                                            aDesktop);
132   addAction("SHOW_ONLY_CMD", anAction);
133
134   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/eye_pencil_closed.png"), tr("Hide"),
135                                            aDesktop);
136   addAction("HIDE_CMD", anAction);
137
138   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/eye_pencil_closed.png"), tr("Hide all"),
139                                            aDesktop);
140   addAction("HIDEALL_CMD", anAction);
141
142   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/shading.png"), tr("Shading"), aDesktop);
143   addAction("SHADING_CMD", anAction);
144
145   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/wireframe.png"), tr("Wireframe"),
146                                            aDesktop);
147   addAction("WIREFRAME_CMD", anAction);
148
149   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/iso_lines.png"), tr("Define Isos..."),
150                                            aDesktop);
151   addAction("ISOLINES_CMD", anAction);
152
153   anAction = ModuleBase_Tools::createAction(QIcon(), tr("Show Isos"), aDesktop);
154   anAction->setCheckable(true);
155   addAction("SHOW_ISOLINES_CMD", anAction);
156
157   mySeparator1 = ModuleBase_Tools::createAction(QIcon(), "", aDesktop);
158   mySeparator1->setSeparator(true);
159
160   mySeparator2 = ModuleBase_Tools::createAction(QIcon(), "", aDesktop);
161   mySeparator2->setSeparator(true);
162
163   mySeparator3 = ModuleBase_Tools::createAction(QIcon(), "", aDesktop);
164   mySeparator3->setSeparator(true);
165
166   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/vertex.png"), tr("Vertices"), aDesktop,
167                                            this, SLOT(onShapeSelection(bool)));
168   anAction->setCheckable(true);
169   addAction("SELECT_VERTEX_CMD", anAction);
170
171   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/edge.png"), tr("Edges"), aDesktop,
172                                            this, SLOT(onShapeSelection(bool)));
173   anAction->setCheckable(true);
174   addAction("SELECT_EDGE_CMD", anAction);
175
176   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/face.png"), tr("Faces"), aDesktop,
177                                            this, SLOT(onShapeSelection(bool)));
178   anAction->setCheckable(true);
179   addAction("SELECT_FACE_CMD", anAction);
180
181   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/result.png"), tr("Results"), aDesktop,
182                                            this, SLOT(onResultSelection(bool)));
183   anAction->setCheckable(true);
184   addAction("SELECT_RESULT_CMD", anAction);
185
186   anAction->setChecked(true);
187
188   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/find_result.png"),
189                                            tr("Select results"), aDesktop);
190   addAction("SHOW_RESULTS_CMD", anAction);
191
192   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/find_result.png"),
193                                            tr("Select parent feature"), aDesktop);
194   addAction("SHOW_FEATURE_CMD", anAction);
195
196 #ifdef TINSPECTOR
197   anAction = ModuleBase_Tools::createAction(QIcon(), tr("TInspector"), aDesktop);
198   addAction("TINSPECTOR_VIEW", anAction);
199 #endif
200
201   // Features folders actions
202   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/create_folder.png"),
203                                            tr("Insert a folder before"), aDesktop);
204   addAction("INSERT_FOLDER_CMD", anAction);
205
206   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/insert_folder_before.png"),
207                                            tr("Move into the previous folder"), aDesktop);
208   addAction("ADD_TO_FOLDER_BEFORE_CMD", anAction);
209
210   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/insert_folder_after.png"),
211                                            tr("Move into the next folder"), aDesktop);
212   addAction("ADD_TO_FOLDER_AFTER_CMD", anAction);
213
214   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_out_before.png"),
215                                            tr("Move out before the folder"), aDesktop);
216   addAction("ADD_OUT_FOLDER_BEFORE_CMD", anAction);
217
218   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_out_after.png"),
219                                            tr("Move out after the folder"), aDesktop);
220   addAction("ADD_OUT_FOLDER_AFTER_CMD", anAction);
221
222   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/normal-view-inversed.png"),
223                                            tr("Set view by inverted normal to face"), aDesktop);
224   addAction("SET_VIEW_INVERTEDNORMAL_CMD", anAction);
225
226   anAction = ModuleBase_Tools::createAction(QIcon(":pictures/normal-view.png"),
227                                            tr("Set view by normal to face"), aDesktop);
228   addAction("SET_VIEW_NORMAL_CMD", anAction);
229
230   buildObjBrowserMenu();
231   buildViewerMenu();
232 }
233
234 void XGUI_ContextMenuMgr::addAction(const QString& theId, QAction* theAction)
235 {
236   if (myActions.contains(theId))
237     qCritical("A command with Id = '%s' already defined!", qPrintable(theId));
238   theAction->setData(theId);
239   connect(theAction, SIGNAL(triggered(bool)), this, SLOT(onAction(bool)));
240   myActions[theId] = theAction;
241 }
242
243 QAction* XGUI_ContextMenuMgr::action(const QString& theId) const
244 {
245   if (myActions.contains(theId))
246     return myActions[theId];
247   return 0;
248 }
249
250 QAction* XGUI_ContextMenuMgr::actionByName(const QString& theName) const
251 {
252   foreach(QAction* eachAction, myActions) {
253     if (eachAction->text() == theName) {
254       return eachAction;
255     }
256   }
257   return NULL;
258 }
259
260 QStringList XGUI_ContextMenuMgr::actionIds() const
261 {
262   return myActions.keys();
263 }
264
265 void XGUI_ContextMenuMgr::onAction(bool isChecked)
266 {
267   QAction* anAction = static_cast<QAction*>(sender());
268   emit actionTriggered(anAction->data().toString(), isChecked);
269 }
270
271 void XGUI_ContextMenuMgr::updateCommandsStatus()
272 {
273 }
274
275 void XGUI_ContextMenuMgr::onContextMenuRequest(QContextMenuEvent* theEvent)
276 {
277   QMenu* aMenu = new QMenu();
278   if (sender() == myWorkshop->objectBrowser()) {
279     updateObjectBrowserMenu();
280     addObjBrowserMenu(aMenu);
281   } else if (sender() == myWorkshop->viewer()) {
282     updateViewerMenu();
283     addViewerMenu(aMenu);
284   }
285
286   if (aMenu && (aMenu->actions().size() > 0)) {
287     // it is possible that some objects should do something before and after the popup menu exec
288     // e.g. a sketch manager changes an internal flag on this signals in order to do not hide
289     // a created entity
290     emit beforeContextMenu();
291     aMenu->exec(theEvent->globalPos());
292     emit afterContextMenu();
293     delete aMenu;
294   }
295 }
296
297 void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
298 {
299   foreach(QAction* anAction, myActions)
300     anAction->setEnabled(false);
301
302   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
303   QObjectPtrList aObjects = aSelMgr->selection()->selectedObjects();
304   int aSelected = aObjects.size();
305   if (aSelected > 0) {
306     SessionPtr aMgr = ModelAPI_Session::get();
307     XGUI_Displayer* aDisplayer = myWorkshop->displayer();
308     bool hasResult = false;
309     bool hasFeature = false;
310     bool hasParameter = false;
311     bool hasCompositeOwner = false;
312     bool hasResultInHistory = false;
313     bool hasFolder = false;
314     ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter,
315                                    hasCompositeOwner, hasResultInHistory, hasFolder);
316     //Process Feature
317     if (aSelected == 1) { // single selection
318       ObjectPtr aObject = aObjects.first();
319       ResultPtr aResult;
320       if (hasResult)
321         aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
322       if (aObject) {
323         if (hasResult && myWorkshop->canBeShaded(aObject)) {
324           XGUI_Displayer::DisplayMode aMode = aDisplayer->displayMode(aObject);
325           if (aMode != XGUI_Displayer::NoMode) {
326             action("WIREFRAME_CMD")->setEnabled(aMode == XGUI_Displayer::Shading);
327             action("SHADING_CMD")->setEnabled(aMode == XGUI_Displayer::Wireframe);
328           } else {
329             action("WIREFRAME_CMD")->setEnabled(true);
330             action("SHADING_CMD")->setEnabled(true);
331           }
332           action("SHOW_ISOLINES_CMD")->setEnabled(true);
333           action("SHOW_ISOLINES_CMD")->setChecked(ModelAPI_Tools::isShownIsoLines(aResult));
334           action("ISOLINES_CMD")->setEnabled(true);
335         }
336         if (!hasFeature) {
337           bool aHasSubResults = ModelAPI_Tools::hasSubResults(aResult);
338           if (aHasSubResults) {
339             action("HIDE_CMD")->setEnabled(true);
340             action("SHOW_CMD")->setEnabled(true);
341           }
342           else {
343             if (aObject->isDisplayed()) {
344               action("HIDE_CMD")->setEnabled(true);
345             } else if (hasResult && (!hasParameter)) {
346               action("SHOW_CMD")->setEnabled(true);
347             }
348           }
349           if (!(hasParameter || hasFeature))
350             action("SHOW_ONLY_CMD")->setEnabled(true);
351         }
352 #ifdef HAVE_SALOME
353         else if (hasFeature && myWorkshop->canMoveFeature()) {
354           action("MOVE_CMD")->setEnabled(true);
355           action("MOVE_SPLIT_CMD")->setEnabled(true);
356         }
357 #endif
358
359         if( aMgr->activeDocument() == aObject->document() )
360         {
361           action("RENAME_CMD")->setEnabled(true);
362           action("DELETE_CMD")->setEnabled(!hasCompositeOwner);
363           action("CLEAN_HISTORY_CMD")->setEnabled(!hasCompositeOwner &&
364                                                   (hasFeature || hasParameter));
365         }
366       }
367       // end single selection
368     } else { // multi-selection
369       // parameter is commented because the actions are not in the list of result parameter actions
370       if (hasResult /*&& (!hasParameter)*/) {
371         action("SHOW_CMD")->setEnabled(true);
372         action("HIDE_CMD")->setEnabled(true);
373         action("SHOW_ONLY_CMD")->setEnabled(true);
374         action("SHADING_CMD")->setEnabled(true);
375         action("WIREFRAME_CMD")->setEnabled(true);
376         action("SHOW_ISOLINES_CMD")->setEnabled(true);
377         action("ISOLINES_CMD")->setEnabled(true);
378       }
379       if (hasFeature && myWorkshop->canMoveFeature()) {
380         action("MOVE_CMD")->setEnabled(true);
381         action("MOVE_SPLIT_CMD")->setEnabled(true);
382       }
383     } // end multi-selection
384
385     // Check folder management commands state if only features are selected
386     if ((!hasResult) && hasFeature && (!hasParameter) && (!hasCompositeOwner) &&
387       (!hasResultInHistory) && (!hasFolder)) {
388       std::list<FeaturePtr> aFeatures = aSelMgr->getSelectedFeatures();
389       if (aFeatures.size() > 0) { // Check that features do not include Parts
390         QModelIndexList aIndexes = aSelMgr->selection()->selectedIndexes();
391         QModelIndex aFirstIdx = aIndexes.first();
392         QModelIndex aLastIdx = aIndexes.last();
393         QModelIndex aParentIdx = aFirstIdx.parent();
394
395         // if all selected are from the same level
396         bool isSameParent = true;
397         foreach(QModelIndex aIdx, aIndexes) {
398           if (aIdx.parent() != aParentIdx) {
399             isSameParent = false;
400             break;
401           }
402         }
403         if (isSameParent) {
404           // Check is selection continuous
405           XGUI_DataModel* aModel = myWorkshop->objectBrowser()->dataModel();
406           DocumentPtr aDoc = aMgr->activeDocument();
407
408           bool isContinuos = true;
409           if (aSelected > 1) {
410             int aId = -1;
411             foreach(FeaturePtr aF, aFeatures) {
412               if (aId == -1)
413                 aId = aDoc->index(aF);
414               else {
415                 aId++;
416                 if (aId != aDoc->index(aF)) {
417                   isContinuos = false;
418                   break;
419                 }
420               }
421             }
422           }
423           if (isContinuos) {
424             ObjectPtr aDataObj = aModel->object(aParentIdx);
425
426             ObjectPtr aPrevObj;
427             if (aFirstIdx.row() > 0) {
428               QModelIndex aPrevIdx = aFirstIdx.sibling(aFirstIdx.row() - 1, 0);
429               aPrevObj = aModel->object(aPrevIdx);
430             }
431
432             ObjectPtr aNextObj;
433             if (aLastIdx.row() < (aModel->rowCount(aParentIdx) - 1)) {
434               QModelIndex aNextIdx = aFirstIdx.sibling(aLastIdx.row() + 1, 0);
435               aNextObj = aModel->object(aNextIdx);
436             }
437
438             bool isPrevFolder = (aPrevObj.get() &&
439               (aPrevObj->groupName() == ModelAPI_Folder::group()));
440             bool isNextFolder = (aNextObj.get() &&
441               (aNextObj->groupName() == ModelAPI_Folder::group()));
442             bool isInFolder = (aDataObj.get() &&
443               (aDataObj->groupName() == ModelAPI_Folder::group()));
444             bool isOutsideFolder = !isInFolder;
445
446             bool hasFirst = false;
447             bool hasLast = false;
448             if (isInFolder) {
449               FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(aDataObj);
450               FeaturePtr aFirstFeatureInFolder;
451               AttributeReferencePtr aFirstFeatAttr =
452                   aFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
453               if (aFirstFeatAttr)
454                 aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
455               hasFirst = (aFirstFeatureInFolder == aFeatures.front());
456
457               FeaturePtr aLastFeatureInFolder;
458               AttributeReferencePtr aLastFeatAttr =
459                   aFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID());
460               if (aLastFeatAttr)
461                 aLastFeatureInFolder = ModelAPI_Feature::feature(aLastFeatAttr->value());
462               hasLast = (aLastFeatureInFolder == aFeatures.back());
463             }
464             action("INSERT_FOLDER_CMD")->setEnabled(isOutsideFolder);
465             action("ADD_TO_FOLDER_BEFORE_CMD")->setEnabled(isOutsideFolder && isPrevFolder);
466             action("ADD_TO_FOLDER_AFTER_CMD")->setEnabled(isOutsideFolder && isNextFolder);
467             action("ADD_OUT_FOLDER_BEFORE_CMD")->setEnabled(isInFolder && hasFirst);
468             action("ADD_OUT_FOLDER_AFTER_CMD")->setEnabled(isInFolder && hasLast);
469           }
470         }
471       }
472     } // end folder management commands
473
474     bool allActive = true;
475     foreach( ObjectPtr aObject, aObjects )
476       if( aMgr->activeDocument() != aObject->document() )  {
477         allActive = false;
478         break;
479       }
480     if (!hasCompositeOwner && allActive ) {
481       if (hasResult || hasFeature || hasParameter) // #2924 results can be erased
482         action("DELETE_CMD")->setEnabled(true);
483     }
484     if (!hasCompositeOwner && allActive && (hasFeature|| hasParameter))
485       action("CLEAN_HISTORY_CMD")->setEnabled(true);
486
487     action("SHOW_RESULTS_CMD")->setEnabled(hasFeature);
488     action("SHOW_FEATURE_CMD")->setEnabled(hasResult && hasResultInHistory);
489   } // end selection processing
490
491   // Show/Hide command has to be disabled for objects from non active document
492   bool aDeactivate = false;
493   foreach (ObjectPtr aObj, aObjects) {
494     if (!aObj->document()->isActive()) {
495       if ((aObj->document() != ModelAPI_Session::get()->moduleDocument()) ||
496            aObj->groupName() == ModelAPI_ResultPart::group()) {
497         aDeactivate = true;
498         break;
499       }
500     }
501   }
502   if (aDeactivate) {
503     // If at leas a one object can not be edited then Show/Hide has to be disabled
504     action("SHOW_CMD")->setEnabled(false);
505     action("HIDE_CMD")->setEnabled(false);
506     action("SHOW_ONLY_CMD")->setEnabled(false);
507   }
508
509   action("COLOR_CMD")->setEnabled(myWorkshop->canChangeProperty("COLOR_CMD"));
510   action("DEFLECTION_CMD")->setEnabled(myWorkshop->canChangeProperty("DEFLECTION_CMD"));
511   action("TRANSPARENCY_CMD")->setEnabled(myWorkshop->canChangeProperty("TRANSPARENCY_CMD"));
512   action("AUTOCOLOR_CMD")->setEnabled(myWorkshop->canChangeProperty("AUTOCOLOR_CMD"));
513
514   #ifdef _DEBUG
515     #ifdef TINSPECTOR
516       action("TINSPECTOR_VIEW")->setEnabled(true);
517     #endif
518   #endif
519
520
521   ModuleBase_IModule* aModule = myWorkshop->module();
522   if (aModule)
523     aModule->updateObjectBrowserMenu(myActions);
524 }
525
526 void XGUI_ContextMenuMgr::updateViewerMenu()
527 {
528   foreach(QAction* anAction, myActions)
529     anAction->setEnabled(false);
530
531   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
532   XGUI_Displayer* aDisplayer = myWorkshop->displayer();
533   QList<ModuleBase_ViewerPrsPtr> aPrsList =
534     aSelMgr->selection()->getSelected(ModuleBase_ISelection::Viewer);
535   if (aPrsList.size() > 0) {
536     bool isVisible = false;
537     bool canBeShaded = false;
538     bool hasPlanar = false;
539     ObjectPtr aObject;
540     foreach(ModuleBase_ViewerPrsPtr aPrs, aPrsList) {
541       aObject = aPrs->object();
542       if (!aObject.get())
543         continue;
544       GeomShapePtr aShape = aPrs->shape();
545       if (aObject->isDisplayed()) {
546         isVisible = true;
547         canBeShaded = aDisplayer->canBeShaded(aObject);
548       }
549       if (aShape.get()) {
550         hasPlanar = (aShape->isFace() && aShape->isPlanar());
551       }
552     }
553     if (isVisible) {
554       if (canBeShaded) {
555         XGUI_Displayer::DisplayMode aMode = aDisplayer->displayMode(aObject);
556         if (aMode != XGUI_Displayer::NoMode) {
557           action("WIREFRAME_CMD")->setEnabled(aMode == XGUI_Displayer::Shading);
558           action("SHADING_CMD")->setEnabled(aMode == XGUI_Displayer::Wireframe);
559         } else {
560           action("WIREFRAME_CMD")->setEnabled(true);
561           action("SHADING_CMD")->setEnabled(true);
562         }
563         action("ISOLINES_CMD")->setEnabled(true);
564
565         if (aPrsList.size() == 1) {
566           ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
567           if (aResult.get()) {
568             action("SHOW_ISOLINES_CMD")->setEnabled(true);
569             action("SHOW_ISOLINES_CMD")->setChecked(ModelAPI_Tools::isShownIsoLines(aResult));
570           }
571         }
572       }
573       action("SHOW_ONLY_CMD")->setEnabled(true);
574       action("HIDE_CMD")->setEnabled(true);
575     } else
576       action("SHOW_CMD")->setEnabled(true);
577
578     action("SET_VIEW_NORMAL_CMD")->setEnabled(hasPlanar);
579     action("SET_VIEW_INVERTEDNORMAL_CMD")->setEnabled(hasPlanar);
580   }
581   //issue #2159 Hide all incomplete behavior
582 #ifdef HAVE_SALOME
583     action("HIDEALL_CMD")->setEnabled(true);
584 #else
585   if (myWorkshop->displayer()->objectsCount() > 0)
586     action("HIDEALL_CMD")->setEnabled(true);
587 #endif
588
589   // Update selection menu
590   QIntList aModes = myWorkshop->selectionActivate()->activeSelectionModes();
591   action("SELECT_VERTEX_CMD")->setEnabled(true);
592   action("SELECT_EDGE_CMD")->setEnabled(true);
593   action("SELECT_FACE_CMD")->setEnabled(true);
594   action("SELECT_RESULT_CMD")->setEnabled(true);
595
596   action("SELECT_RESULT_CMD")->setChecked(false);
597   action("SELECT_VERTEX_CMD")->setChecked(false);
598   action("SELECT_EDGE_CMD")->setChecked(false);
599   action("SELECT_FACE_CMD")->setChecked(false);
600   action("SELECT_RESULT_CMD")->setChecked(false);
601   if (aModes.count() == 0) {
602     action("SELECT_RESULT_CMD")->setChecked(true);
603   } else {
604     foreach(int aMode, aModes) {
605       switch (aMode) {
606       case TopAbs_VERTEX:
607         action("SELECT_VERTEX_CMD")->setChecked(true);
608         break;
609       case TopAbs_EDGE:
610         action("SELECT_EDGE_CMD")->setChecked(true);
611         break;
612       case TopAbs_FACE:
613         action("SELECT_FACE_CMD")->setChecked(true);
614         break;
615       default:
616         action("SELECT_RESULT_CMD")->setChecked(true);
617       }
618     }
619   }
620
621   ModuleBase_IModule* aModule = myWorkshop->module();
622   if (aModule)
623     aModule->updateViewerMenu(myActions);
624
625   if (myWorkshop->canChangeProperty("COLOR_CMD"))
626     action("COLOR_CMD")->setEnabled(true);
627
628   if (myWorkshop->canChangeProperty("DEFLECTION_CMD"))
629     action("DEFLECTION_CMD")->setEnabled(true);
630
631   if (myWorkshop->canChangeProperty("TRANSPARENCY_CMD"))
632     action("TRANSPARENCY_CMD")->setEnabled(true);
633
634   action("DELETE_CMD")->setEnabled(true);
635 }
636
637 void XGUI_ContextMenuMgr::connectObjectBrowser()
638 {
639   connect(myWorkshop->objectBrowser(), SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
640           SLOT(onContextMenuRequest(QContextMenuEvent*)));
641 }
642
643 void XGUI_ContextMenuMgr::connectViewer()
644 {
645   connect(myWorkshop->viewer(), SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
646           SLOT(onContextMenuRequest(QContextMenuEvent*)));
647 }
648
649
650 void XGUI_ContextMenuMgr::buildObjBrowserMenu()
651 {
652   QAction* aSeparator = ModuleBase_Tools::createAction(QIcon(), "", myWorkshop->desktop());
653   aSeparator->setSeparator(true);
654
655   QActionsList aList;
656
657   // Result construction menu
658   aList.append(action("SHOW_CMD"));
659   aList.append(action("HIDE_CMD"));
660   aList.append(action("SHOW_ONLY_CMD"));
661   aList.append(mySeparator1);
662   aList.append(action("RENAME_CMD"));
663   aList.append(action("COLOR_CMD"));
664   aList.append(action("DEFLECTION_CMD"));
665   aList.append(action("TRANSPARENCY_CMD"));
666   aList.append(action("SHOW_FEATURE_CMD"));
667   aList.append(mySeparator2);
668   aList.append(action("DELETE_CMD"));
669   myObjBrowserMenus[ModelAPI_ResultConstruction::group()] = aList;
670
671   //-------------------------------------
672   // Result body menu
673   aList.clear();
674   aList.append(action("WIREFRAME_CMD"));
675   aList.append(action("SHADING_CMD"));
676   aList.append(mySeparator1); // this separator is not shown as this action is added after show only
677   // qt list container contains only one instance of the same action
678   aList.append(action("SHOW_CMD"));
679   aList.append(action("HIDE_CMD"));
680   aList.append(action("SHOW_ONLY_CMD"));
681   aList.append(mySeparator2);
682   aList.append(action("RENAME_CMD"));
683   aList.append(action("COLOR_CMD"));
684   aList.append(action("DEFLECTION_CMD"));
685   aList.append(action("TRANSPARENCY_CMD"));
686   aList.append(action("SHOW_ISOLINES_CMD"));
687   aList.append(action("ISOLINES_CMD"));
688   aList.append(action("SHOW_FEATURE_CMD"));
689   aList.append(mySeparator3);
690   aList.append(action("DELETE_CMD"));
691   myObjBrowserMenus[ModelAPI_ResultBody::group()] = aList;
692   // Group menu
693   myObjBrowserMenus[ModelAPI_ResultField::group()] = aList;
694   // Result part menu
695   myObjBrowserMenus[ModelAPI_ResultPart::group()] = aList;
696
697   aList.clear();
698   aList.append(action("WIREFRAME_CMD"));
699   aList.append(action("SHADING_CMD"));
700   aList.append(mySeparator1); // this separator is not shown as this action is added after show only
701   // qt list container contains only one instance of the same action
702   aList.append(action("SHOW_CMD"));
703   aList.append(action("HIDE_CMD"));
704   aList.append(action("SHOW_ONLY_CMD"));
705   aList.append(mySeparator2);
706   aList.append(action("AUTOCOLOR_CMD"));
707   aList.append(action("RENAME_CMD"));
708   aList.append(action("COLOR_CMD"));
709   aList.append(action("DEFLECTION_CMD"));
710   aList.append(action("TRANSPARENCY_CMD"));
711   aList.append(action("SHOW_ISOLINES_CMD"));
712   aList.append(action("ISOLINES_CMD"));
713   aList.append(action("SHOW_FEATURE_CMD"));
714   aList.append(mySeparator3);
715   aList.append(action("DELETE_CMD"));
716   // Group menu
717   myObjBrowserMenus[ModelAPI_ResultGroup::group()] = aList;
718   //-------------------------------------
719   // Feature menu
720   aList.clear();
721   aList.append(action("RENAME_CMD"));
722   aList.append(action("SHOW_RESULTS_CMD"));
723   aList.append(action("MOVE_CMD"));
724   aList.append(action("MOVE_SPLIT_CMD"));
725   aList.append(mySeparator1);
726   aList.append(action("INSERT_FOLDER_CMD"));
727   aList.append(action("ADD_TO_FOLDER_BEFORE_CMD"));
728   aList.append(action("ADD_TO_FOLDER_AFTER_CMD"));
729   aList.append(mySeparator2);
730   aList.append(action("ADD_OUT_FOLDER_BEFORE_CMD"));
731   aList.append(action("ADD_OUT_FOLDER_AFTER_CMD"));
732   aList.append(mySeparator3);
733   aList.append(action("CLEAN_HISTORY_CMD"));
734   aList.append(action("DELETE_CMD"));
735   myObjBrowserMenus[ModelAPI_Feature::group()] = aList;
736
737   aList.clear();
738   aList.append(action("RENAME_CMD"));
739   aList.append(mySeparator1);
740   aList.append(action("CLEAN_HISTORY_CMD"));
741   aList.append(action("DELETE_CMD"));
742   myObjBrowserMenus[ModelAPI_ResultParameter::group()] = aList;
743   //-------------------------------------
744
745   aList.clear();
746   aList.append(action("RENAME_CMD"));
747   aList.append(action("DELETE_CMD"));
748   myObjBrowserMenus[ModelAPI_Folder::group()] = aList;
749
750   //---------------------------------------
751   // Step objects menu
752   aList.clear();
753   aList.append(action("SHOW_CMD"));
754   aList.append(action("HIDE_CMD"));
755   aList.append(action("SHOW_ONLY_CMD"));
756   myObjBrowserMenus[ModelAPI_ResultField::ModelAPI_FieldStep::group()] = aList;
757 }
758
759 void XGUI_ContextMenuMgr::buildViewerMenu()
760 {
761   QActionsList aList;
762   // Result construction menu
763   aList.append(action("COLOR_CMD"));
764   aList.append(action("DEFLECTION_CMD"));
765   aList.append(action("TRANSPARENCY_CMD"));
766   aList.append(mySeparator3);
767   aList.append(action("SET_VIEW_NORMAL_CMD"));
768   aList.append(action("SET_VIEW_INVERTEDNORMAL_CMD"));
769   aList.append(mySeparator1);
770   aList.append(action("SHOW_ONLY_CMD"));
771   aList.append(action("HIDE_CMD"));
772   myViewerMenu[ModelAPI_ResultConstruction::group()] = aList;
773   // Result part menu
774   myViewerMenu[ModelAPI_ResultPart::group()] = aList;
775   //-------------------------------------
776   // Result body menu
777   aList.clear();
778   aList.append(action("WIREFRAME_CMD"));
779   aList.append(action("SHADING_CMD"));
780   aList.append(mySeparator2);
781   aList.append(action("COLOR_CMD"));
782   aList.append(action("DEFLECTION_CMD"));
783   aList.append(action("TRANSPARENCY_CMD"));
784   aList.append(action("SHOW_ISOLINES_CMD"));
785   aList.append(action("ISOLINES_CMD"));
786   aList.append(mySeparator3);
787   aList.append(action("SET_VIEW_NORMAL_CMD"));
788   aList.append(action("SET_VIEW_INVERTEDNORMAL_CMD"));
789   aList.append(mySeparator1);
790   aList.append(action("SHOW_ONLY_CMD"));
791   aList.append(action("HIDE_CMD"));
792   myViewerMenu[ModelAPI_ResultBody::group()] = aList;
793   // Group menu
794   myViewerMenu[ModelAPI_ResultGroup::group()] = aList;
795   myViewerMenu[ModelAPI_ResultField::group()] = aList;
796   //-------------------------------------
797   // Step objects menu
798   aList.clear();
799   aList.append(action("HIDE_CMD"));
800   myViewerMenu[ModelAPI_ResultField::ModelAPI_FieldStep::group()] = aList;
801 }
802
803
804 void XGUI_ContextMenuMgr::addObjBrowserMenu(QMenu* theMenu) const
805 {
806   ModuleBase_IModule* aModule = myWorkshop->module();
807   if (aModule) {
808     theMenu->addSeparator();
809     aModule->addObjectBrowserMenu(theMenu);
810   }
811
812   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
813   QObjectPtrList aObjects = aSelMgr->selection()->selectedObjects();
814   int aSelected = aObjects.size();
815   QActionsList anActions;
816   if (aSelected == 1) {
817     ObjectPtr aObject = aObjects.first();
818     std::string aName = aObject->groupName();
819     if (myObjBrowserMenus.contains(aName))
820       anActions = myObjBrowserMenus[aName];
821   } else if (aSelected > 1) {
822       anActions.append(action("WIREFRAME_CMD"));
823       anActions.append(action("SHADING_CMD"));
824       anActions.append(mySeparator1);
825       anActions.append(action("SHOW_CMD"));
826       anActions.append(action("HIDE_CMD"));
827       anActions.append(action("SHOW_ONLY_CMD"));
828       anActions.append(mySeparator2);
829       anActions.append(action("ADD_TO_FOLDER_BEFORE_CMD"));
830       anActions.append(action("ADD_TO_FOLDER_AFTER_CMD"));
831       anActions.append(action("ADD_OUT_FOLDER_BEFORE_CMD"));
832       anActions.append(action("ADD_OUT_FOLDER_AFTER_CMD"));
833       anActions.append(mySeparator3);
834       anActions.append(action("MOVE_CMD"));
835       anActions.append(action("MOVE_SPLIT_CMD"));
836       anActions.append(action("COLOR_CMD"));
837       anActions.append(action("DEFLECTION_CMD"));
838       anActions.append(action("TRANSPARENCY_CMD"));
839       anActions.append(action("SHOW_ISOLINES_CMD"));
840       anActions.append(action("ISOLINES_CMD"));
841       anActions.append(action("CLEAN_HISTORY_CMD"));
842       anActions.append(action("DELETE_CMD"));
843   }
844 #ifdef _DEBUG
845   if (aSelected == 0) {
846     #ifdef TINSPECTOR
847     anActions.append(action("TINSPECTOR_VIEW"));
848     #endif
849   }
850 #endif
851   theMenu->addActions(anActions);
852   addFeatures(theMenu);
853
854   // It is commented out because Object Browser does not have actions
855   //theMenu->addSeparator();
856   //theMenu->addActions(myWorkshop->objectBrowser()->actions());
857 }
858
859 void XGUI_ContextMenuMgr::addViewerMenu(QMenu* theMenu) const
860 {
861   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
862   QList<ModuleBase_ViewerPrsPtr> aPrsList =
863     aSelMgr->selection()->getSelected(ModuleBase_ISelection::Viewer);
864   int aSelected = aPrsList.size();
865   QActionsList anActions;
866
867   // Create selection menu
868   XGUI_OperationMgr* aOpMgr = myWorkshop->operationMgr();
869   if (!aOpMgr->hasOperation() &&
870       myWorkshop->selectionActivate()->activeSelectionPlace() == XGUI_SelectionActivate::Workshop) {
871     QMenu* aSelMenu = new QMenu(tr("Selection mode"), theMenu);
872     aSelMenu->addAction(action("SELECT_VERTEX_CMD"));
873     aSelMenu->addAction(action("SELECT_EDGE_CMD"));
874     aSelMenu->addAction(action("SELECT_FACE_CMD"));
875     //IMP: an attempt to use result selection with other selection modes
876     //aSelMenu->addSeparator();
877     aSelMenu->addAction(action("SELECT_RESULT_CMD"));
878     theMenu->addMenu(aSelMenu);
879     theMenu->addSeparator();
880   }
881   if (aSelected == 1) {
882     ObjectPtr aObject = aPrsList.first()->object();
883     if (aObject.get() != NULL) {
884       std::string aName = aObject->groupName();
885       if (myViewerMenu.contains(aName))
886         anActions = myViewerMenu[aName];
887     }
888   } else if (aSelected > 1) {
889     anActions.append(action("COLOR_CMD"));
890     anActions.append(action("DEFLECTION_CMD"));
891     anActions.append(action("TRANSPARENCY_CMD"));
892     anActions.append(mySeparator1);
893     anActions.append(action("SHOW_ONLY_CMD"));
894     anActions.append(action("HIDE_CMD"));
895   }
896   // hide all is shown always even if selection in the viewer is empty
897   anActions.append(action("HIDEALL_CMD"));
898   theMenu->addActions(anActions);
899
900   QMap<int, QAction*> aMenuActions;
901   ModuleBase_IModule* aModule = myWorkshop->module();
902   if (aModule) {
903     if (aModule->addViewerMenu(myActions, theMenu, aMenuActions))
904       theMenu->addSeparator();
905   }
906
907   // insert the module menu items on specific positions in the popup menu: some actions should be
908   // in the begin of the list, Delete action should be the last by #1343 issue
909   QList<QAction*> anActionsList = theMenu->actions();
910   int anActionsListSize = anActionsList.size();
911   QAction* aFirstAction = anActionsList[0];
912   QMap<int, QAction*>::const_iterator anIt = aMenuActions.begin(), aLast = aMenuActions.end();
913   for (; anIt != aLast; anIt++) {
914     if (anIt.key() > anActionsListSize)
915       theMenu->addAction(anIt.value());
916     else
917       theMenu->insertAction(aFirstAction, *anIt);
918   }
919
920 #ifndef HAVE_SALOME
921   theMenu->addSeparator();
922   QMdiArea* aMDI = myWorkshop->mainWindow()->mdiArea();
923   if (aMDI->actions().size() > 0) {
924     QMenu* aSubMenu = theMenu->addMenu(tr("Windows"));
925     aSubMenu->addActions(aMDI->actions());
926   }
927 #endif
928 }
929
930 QStringList XGUI_ContextMenuMgr::actionObjectGroups(const QString& theName)
931 {
932   QStringList aGroups;
933
934   QMap<std::string, QActionsList>::const_iterator anIt = myObjBrowserMenus.begin(),
935                                                   aLast = myObjBrowserMenus.end();
936   for (; anIt != aLast; anIt++) {
937     QString aGroupName(anIt.key().c_str());
938     if (aGroups.contains(aGroupName))
939       continue;
940     QActionsList anActions = anIt.value();
941     QActionsList::const_iterator anAIt = anActions.begin(), anALast = anActions.end();
942     bool aFound = false;
943     for (; anAIt != anALast && !aFound; anAIt++)
944       aFound = (*anAIt)->data().toString() == theName;
945     if (aFound)
946       aGroups.append(aGroupName);
947   }
948   return aGroups;
949 }
950
951 void XGUI_ContextMenuMgr::onRename()
952 {
953   QObjectPtrList anObjects = myWorkshop->selector()->selection()->selectedObjects();
954   if (!myWorkshop->abortAllOperations())
955     return;
956   // restore selection in case if dialog box was shown
957   myWorkshop->objectBrowser()->setObjectsSelected(anObjects);
958   myWorkshop->objectBrowser()->onEditItem();
959 }
960
961 void XGUI_ContextMenuMgr::addFeatures(QMenu* theMenu) const
962 {
963   SessionPtr aMgr = ModelAPI_Session::get();
964   DocumentPtr anActiveDoc = aMgr->activeDocument();
965
966   XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
967   XGUI_ActionsMgr* anActionMgr = myWorkshop->actionsMgr();
968   const Config_DataModelReader* aDataModelXML = myWorkshop->dataModelXMLReader();
969   QModelIndexList aSelectedIndexes = aSelMgr->selection()->selectedIndexes();
970
971   QString aName;
972   int aLen = 0;
973   bool aIsRoot = false;
974   foreach(QModelIndex aIdx, aSelectedIndexes) {
975     // Process only first column
976     if (aIdx.column() == 1) {
977       aIsRoot = !aIdx.parent().isValid();
978       // Exit if the selected index belongs to non active document
979       if (aIsRoot && (anActiveDoc != aMgr->moduleDocument()))
980         return;
981
982       // Get name of the selected index
983       aName = aIdx.data().toString();
984       aLen = aName.indexOf('(');
985       if (aLen != -1) {
986         aName = aName.left(--aLen);
987       }
988       std::string aFeaturesStr = aIsRoot?
989         aDataModelXML->rootFolderFeatures(aName.toStdString()) :
990         aDataModelXML->subFolderFeatures(aName.toStdString());
991         if (aFeaturesStr.length() > 0) {
992           QStringList aFeturesList =
993             QString(aFeaturesStr.c_str()).split(",", QString::SkipEmptyParts);
994           foreach(QString aFea, aFeturesList) {
995             QAction* anAction = anActionMgr->action(aFea);
996             if (anAction)
997               theMenu->addAction(anAction);
998           }
999         }
1000     }
1001   }
1002 }
1003
1004 #define UNCHECK_ACTION(NAME) \
1005 { QAction* anAction = action(NAME); \
1006 bool isBlock = anAction->signalsBlocked(); \
1007 anAction->blockSignals(true); \
1008 anAction->setChecked(false); \
1009   anAction->blockSignals(isBlock); }
1010
1011
1012 void XGUI_ContextMenuMgr::onResultSelection(bool theChecked)
1013 {
1014   UNCHECK_ACTION("SELECT_VERTEX_CMD");
1015   UNCHECK_ACTION("SELECT_EDGE_CMD");
1016   UNCHECK_ACTION("SELECT_FACE_CMD");
1017 }
1018
1019 void XGUI_ContextMenuMgr::onShapeSelection(bool theChecked)
1020 {
1021   UNCHECK_ACTION("SHOW_RESULTS_CMD");
1022 }