Salome HOME
Issue 1303 Re-ordering of Sketcher menus: using menu mechanizm to group SALOME actions.
[modules/shaper.git] / src / XGUI / XGUI_MenuMgr.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        XGUI_MenuMgr.cpp
4 // Created:     13 Apr 2016
5 // Author:      Natalia ERMOLAEVA
6
7 #include <XGUI_MenuMgr.h>
8 #include <XGUI_Workshop.h>
9 #include <XGUI_ActionsMgr.h>
10 #include <XGUI_OperationMgr.h>
11 #include <XGUI_MenuWorkbench.h>
12 #include <XGUI_MenuGroup.h>
13
14 #include <Events_Loop.h>
15 #include <Config_FeatureMessage.h>
16 #include <Config_Keywords.h>
17
18 #ifndef HAVE_SALOME
19 #include <AppElements_Workbench.h>
20 #include <AppElements_Command.h>
21 #include <AppElements_MainMenu.h>
22 #include <AppElements_MainWindow.h>
23 #include <AppElements_MenuGroupPanel.h>
24 #include <AppElements_Button.h>
25 #else
26 #include <XGUI_SalomeConnector.h>
27 #endif
28
29 #include <ModuleBase_IModule.h>
30
31 #include <QObject>
32 #include <QAction>
33 #include <QDebug>
34
35 XGUI_MenuMgr::XGUI_MenuMgr(XGUI_Workshop* theWorkshop)
36 : myWorkshop(theWorkshop)
37 {
38   Events_Loop* aLoop = Events_Loop::loop();
39
40   aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT()));
41 }
42
43 void XGUI_MenuMgr::processEvent(const std::shared_ptr<Events_Message>& theMessage)
44 {
45   //A message to start feature creation received.
46   if (theMessage->eventID() == Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) {
47     std::shared_ptr<Config_FeatureMessage> aFeatureMsg =
48        std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
49     if (!aFeatureMsg->isInternal()) {
50       addFeature(aFeatureMsg);
51     }
52   }
53 }
54
55 void XGUI_MenuMgr::addFeature(const std::shared_ptr<Config_FeatureMessage>& theMessage)
56 {
57   if (!theMessage) {
58 #ifdef _DEBUG
59     qDebug() << "XGUI_WorkshopListener::addFeature: NULL message.";
60 #endif
61     return;
62   }
63 #ifdef HAVE_SALOME
64   std::shared_ptr<XGUI_MenuWorkbench> aWorkbench = findWorkbench(theMessage->workbenchId());
65   std::shared_ptr<XGUI_MenuGroup> aGroup = aWorkbench->findGroup(theMessage->groupId());
66   aGroup->setFeatureInfo(theMessage);
67 #else
68   ActionInfo aFeatureInfo;
69   aFeatureInfo.initFrom(theMessage);
70
71   QString aWchName = QString::fromStdString(theMessage->workbenchId());
72   QStringList aNestedFeatures =
73       QString::fromStdString(theMessage->nestedFeatures()).split(" ", QString::SkipEmptyParts);
74   QList<QAction*> aNestedActList;
75   bool isColumnButton = !aNestedFeatures.isEmpty();
76   if (isColumnButton) {
77     QString aNestedActions = QString::fromStdString(theMessage->actionsWhenNested());
78     XGUI_OperationMgr* anOperationMgr = myWorkshop->operationMgr();
79     XGUI_ActionsMgr* anActionsMgr = myWorkshop->actionsMgr();
80     if (aNestedActions.contains(FEATURE_WHEN_NESTED_ACCEPT)) {
81       QAction* anAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL);
82       QObject::connect(anAction, SIGNAL(triggered()), anOperationMgr, SLOT(commitAllOperations()));
83       aNestedActList << anAction;
84     }
85     if (aNestedActions.contains(FEATURE_WHEN_NESTED_ABORT)) {
86       QAction* anAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll, NULL);
87       QObject::connect(anAction, SIGNAL(triggered()), anOperationMgr, SLOT(abortAllOperations()));
88       aNestedActList << anAction;
89     }
90   }
91
92   //Find or create Workbench
93   AppElements_MainMenu* aMenuBar = myWorkshop->mainWindow()->menuObject();
94   AppElements_Workbench* aPage = aMenuBar->findWorkbench(aWchName);
95   if (!aPage) {
96     aPage = myWorkshop->addWorkbench(aWchName);
97   }
98   //Find or create Group
99   QString aGroupName = QString::fromStdString(theMessage->groupId());
100   AppElements_MenuGroupPanel* aGroup = aPage->findGroup(aGroupName);
101   if (!aGroup) {
102     aGroup = aPage->addGroup(aGroupName);
103   }
104   // Check if hotkey sequence is already defined:
105   XGUI_ActionsMgr* anActionsMgr = myWorkshop->actionsMgr();
106   QKeySequence aHotKey = anActionsMgr->registerShortcut(aFeatureInfo.shortcut);
107   if(aHotKey != aFeatureInfo.shortcut) {
108     aFeatureInfo.shortcut = aHotKey;
109   }
110   AppElements_Command* aCommand = aGroup->addFeature(theMessage);
111   // Enrich created button with accept/abort buttons if necessary
112   AppElements_Button* aButton = aCommand->button();
113   if (aButton->isColumnButton()) {
114     aButton->setAdditionalButtons(aNestedActList);
115   }
116   myWorkshop->actionsMgr()->addCommand(aCommand);
117   myWorkshop->module()->actionCreated(aCommand);
118 #endif
119 }
120
121 std::shared_ptr<XGUI_MenuWorkbench> XGUI_MenuMgr::findWorkbench(const std::string& theWorkbenchName)
122 {
123   std::list< std::shared_ptr<XGUI_MenuWorkbench> >::const_iterator anIt = myWorkbenches.begin(),
124                                                                    aLast = myWorkbenches.end();
125   std::shared_ptr<XGUI_MenuWorkbench> aResultWorkbench;
126   for (; anIt != aLast && !aResultWorkbench; anIt++) {
127     std::shared_ptr<XGUI_MenuWorkbench> aWorkbench = *anIt;
128     if (aWorkbench->getName() == theWorkbenchName)
129       aResultWorkbench = aWorkbench;
130   }
131   if (!aResultWorkbench) {
132     aResultWorkbench = std::shared_ptr<XGUI_MenuWorkbench>(new XGUI_MenuWorkbench(theWorkbenchName));
133     myWorkbenches.push_back(aResultWorkbench);
134   }
135   return aResultWorkbench;
136 }
137
138 void XGUI_MenuMgr::createFeatureActions()
139 {
140 #ifdef HAVE_SALOME
141   std::list< std::shared_ptr<XGUI_MenuWorkbench> >::const_iterator anIt = myWorkbenches.begin(),
142                                                                    aLast = myWorkbenches.end();
143   XGUI_SalomeConnector* aSalomeConnector = myWorkshop->salomeConnector();
144   for (; anIt != aLast; anIt++) {
145     std::shared_ptr<XGUI_MenuWorkbench> aWorkbench = *anIt;
146     std::string aWchName = aWorkbench->getName();
147     const std::list<std::shared_ptr<XGUI_MenuGroup> >& aGroups = aWorkbench->groups();
148     std::list<std::shared_ptr<XGUI_MenuGroup> >::const_iterator aGIt = aGroups.begin(),
149                                                                 aGLast = aGroups.end();
150     for (; aGIt != aGLast; aGIt++) {
151       const std::shared_ptr<XGUI_MenuGroup> aGroup = *aGIt;
152       std::string aGName = aGroup->getName();
153       const std::list<std::shared_ptr<Config_FeatureMessage> >& aFeaturesInfo = aGroup->featuresInfo();
154       std::list<std::shared_ptr<Config_FeatureMessage> >::const_iterator aFIt = aFeaturesInfo.begin(),
155                                                                                aFLast = aFeaturesInfo.end();
156       int aFSize = aFeaturesInfo.size();
157       for(int i = 0; aFIt != aFLast; aFIt++, i++) {
158         std::shared_ptr<Config_FeatureMessage> aMessage = *aFIt;
159         bool aUseSeparator = i == aFSize-1;
160         QAction* aAction = buildAction(aMessage, aWchName, aUseSeparator);
161
162         aSalomeConnector->setFeatureInfo(QString::fromStdString(aMessage->id()), aMessage);
163         myWorkshop->actionsMgr()->addCommand(aAction);
164         myWorkshop->module()->actionCreated(aAction);
165       }
166     }
167   }
168 #endif
169 }
170
171 QAction* XGUI_MenuMgr::buildAction(const std::shared_ptr<Config_FeatureMessage>& theMessage,
172                                    const std::string& theWchName, const bool aUseSeparator) const
173 {
174   QAction* anAction;
175
176 #ifdef HAVE_SALOME
177   XGUI_SalomeConnector* aSalomeConnector = myWorkshop->salomeConnector();
178
179   ActionInfo aFeatureInfo;
180   aFeatureInfo.initFrom(theMessage);
181   QStringList aNestedFeatures =
182       QString::fromStdString(theMessage->nestedFeatures()).split(" ", QString::SkipEmptyParts);
183   QList<QAction*> aNestedActList;
184   if (!aNestedFeatures.isEmpty()) {
185     QString aNestedActions = QString::fromStdString(theMessage->actionsWhenNested());
186     XGUI_OperationMgr* anOperationMgr = myWorkshop->operationMgr();
187     XGUI_ActionsMgr* anActionsMgr = myWorkshop->actionsMgr();
188     if (aNestedActions.contains(FEATURE_WHEN_NESTED_ACCEPT)) {
189       QAction* anAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL);
190       QObject::connect(anAction, SIGNAL(triggered()), anOperationMgr, SLOT(commitAllOperations()));
191       aNestedActList << anAction;
192     }
193     if (aNestedActions.contains(FEATURE_WHEN_NESTED_ABORT)) {
194       QAction* anAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll, NULL);
195       QObject::connect(anAction, SIGNAL(triggered()), anOperationMgr, SLOT(abortAllOperations()));
196       aNestedActList << anAction;
197     }
198     anAction = aSalomeConnector->addFeatureOfNested(theWchName.c_str(), aFeatureInfo,
199                                                     aNestedActList, false, true);
200     QAction* aMenuAction = aSalomeConnector->addFeature(theWchName.c_str(), aFeatureInfo,
201                                                     aUseSeparator, true, false);
202     myWorkshop->module()->actionCreated(aMenuAction);
203   }
204   else {
205     //Issue #650: in the SALOME mode the tooltip should be same as text
206     aFeatureInfo.toolTip = aFeatureInfo.text;
207     anAction = aSalomeConnector->addFeature(theWchName.c_str(), aFeatureInfo, aUseSeparator);
208   }
209 #endif
210   return anAction;
211 }