]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_ActionsMgr.cpp
Salome HOME
Issue #1063: Use selection validators in update of ActionMgr. Equal constraint select...
[modules/shaper.git] / src / XGUI / XGUI_ActionsMgr.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 /*
4  * XGUI_ActionsMgr.cpp
5  */
6
7 #include <AppElements_Command.h>
8
9 #include <XGUI_ActionsMgr.h>
10 #include <XGUI_Workshop.h>
11 #include <XGUI_OperationMgr.h>
12 #include <XGUI_SalomeConnector.h>
13 #include <XGUI_Selection.h>
14 #include <XGUI_SelectionMgr.h>
15
16 #include <Events_Loop.h>
17 #include <Events_Error.h>
18
19 #include <ModelAPI_Session.h>
20 #include <ModelAPI_Events.h>
21 #include <ModelAPI_Validator.h>
22 #include <ModuleBase_Operation.h>
23 #include <ModuleBase_OperationFeature.h>
24 #include <ModuleBase_SelectionValidator.h>
25
26
27 #include <QAction>
28
29 #ifdef _DEBUG
30 #include <iostream>
31 #include <QDebug>
32 #endif
33
34 XGUI_ActionsMgr::XGUI_ActionsMgr(XGUI_Workshop* theParent)
35     : QObject(theParent),
36       myWorkshop(theParent),
37       myOperationMgr(theParent->operationMgr())
38 {
39   // Default shortcuts
40   myShortcuts << QKeySequence::Save;
41   myShortcuts << QKeySequence::Undo;
42   myShortcuts << QKeySequence::Redo;
43   myShortcuts << QKeySequence::Open;
44   myShortcuts << QKeySequence::Close;
45
46   //Initialize event listening
47   Events_Loop* aLoop = Events_Loop::loop();
48   static Events_ID aStateResponseEventId =
49       Events_Loop::loop()->eventByName(EVENT_FEATURE_STATE_RESPONSE);
50   aLoop->registerListener(this, aStateResponseEventId, NULL, true);
51 }
52
53 XGUI_ActionsMgr::~XGUI_ActionsMgr()
54 {
55 }
56
57 void XGUI_ActionsMgr::addCommand(QAction* theCmd)
58 {
59   QString aId = theCmd->data().toString();
60   if (aId.isEmpty()) {
61     return;
62   }
63   myActions.insert(aId, theCmd);
64   AppElements_Command* aXCmd = dynamic_cast<AppElements_Command*>(theCmd);
65   if (aXCmd) {
66     myNestedActions[aId] = aXCmd->nestedCommands();
67   } else {
68     XGUI_Workshop* aWorkshop = static_cast<XGUI_Workshop*>(parent());
69     myNestedActions[aId] = aWorkshop->salomeConnector()->nestedActions(aId);
70   }
71 }
72
73 void XGUI_ActionsMgr::addNestedCommands(const QString& theId, const QStringList& theCommands)
74 {
75   myNestedActions[theId] = theCommands;
76 }
77
78 QStringList XGUI_ActionsMgr::nestedCommands(const QString& theId) const
79 {
80   if (myNestedActions.contains(theId))
81     return myNestedActions[theId];
82   return QStringList();
83 }
84
85 bool XGUI_ActionsMgr::isNested(const QString& theId) const
86 {
87   foreach(QString aId, myNestedActions.keys())
88   {
89     QStringList aList = myNestedActions[aId];
90     if (aList.contains(theId))
91       return true;
92   }
93   return false;
94 }
95
96 void XGUI_ActionsMgr::update()
97 {
98   XGUI_Selection* aSelection = myWorkshop->selector()->selection();
99   if (aSelection->getSelected(ModuleBase_ISelection::Viewer).size() > 0) {
100     updateOnViewSelection();
101   } else {
102     FeaturePtr anActiveFeature = FeaturePtr();
103     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
104                                                            (myOperationMgr->currentOperation());
105     if (aFOperation) {
106       anActiveFeature = aFOperation->feature();
107       if(anActiveFeature.get()) {
108         setAllEnabled(false);
109         QString aFeatureId = QString::fromStdString(anActiveFeature->getKind());
110         setActionEnabled(aFeatureId, true);
111       }
112       setNestedStackEnabled(aFOperation);
113     } else {
114       setAllEnabled(true);
115       setNestedCommandsEnabled(false);
116     }
117     // TODO(SBH): Get defaults state of actions from XML and remove the following method
118     updateByDocumentKind();
119     updateCheckState();
120     updateByPlugins(anActiveFeature);
121   }
122 }
123
124 void XGUI_ActionsMgr::updateCheckState()
125 {
126   QString eachCommand = QString();
127   foreach(eachCommand, myActions.keys()) {
128     setActionChecked(eachCommand, false);
129   }
130   QStringList ltActiveCommands = myOperationMgr->operationList();
131   foreach(eachCommand, ltActiveCommands) {
132     setActionChecked(eachCommand, true);
133   }
134 }
135
136 void XGUI_ActionsMgr::updateOnViewSelection()
137 {
138   if (!myOperationMgr->hasOperation())
139     return;
140
141   QStringList aIdList = myOperationMgr->operationList();
142   //ModuleBase_Operation* anOperation = myOperationMgr->currentOperation();
143   //FeaturePtr anActiveFeature = anOperation->feature();
144   //if(!anActiveFeature.get())
145   if (aIdList.isEmpty())
146     return;
147
148   ModuleBase_Operation* theOperation = myOperationMgr->currentOperation();
149   //QString aFeatureId = QString::fromStdString(anActiveFeature->getKind());
150   XGUI_Selection* aSelection = myWorkshop->selector()->selection();
151   // only viewer selection is processed
152   SessionPtr aMgr = ModelAPI_Session::get();
153   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
154   foreach(QString aFeatureId, aIdList) {
155     foreach(QString aId, nestedCommands(aFeatureId)) {
156       ModelAPI_ValidatorsFactory::Validators aValidators;
157       aFactory->validators(aId.toStdString(), aValidators);
158       ModelAPI_ValidatorsFactory::Validators::iterator aValidatorIt = aValidators.begin();
159       for (; aValidatorIt != aValidators.end(); ++aValidatorIt) {
160         const ModuleBase_SelectionValidator* aSelValidator =
161             dynamic_cast<const ModuleBase_SelectionValidator*>(aFactory->validator(aValidatorIt->first));
162         if (aSelValidator)
163           setActionEnabled(aId, aSelValidator->isValid(aSelection, theOperation));
164       }
165     }
166   }
167 }
168
169 QKeySequence XGUI_ActionsMgr::registerShortcut(const QKeySequence& theKeySequence)
170 {
171   if (theKeySequence.isEmpty()) {
172     return QKeySequence();
173   }
174   if (myShortcuts.contains(theKeySequence)) {
175     QString aMessage = tr("Shortcut %1 is already defined. Ignore.");
176     aMessage = aMessage.arg(theKeySequence.toString());
177     Events_Error::send(aMessage.toStdString());
178     return QKeySequence();
179   }
180   myShortcuts.append(theKeySequence);
181   return theKeySequence;
182 }
183
184 QKeySequence XGUI_ActionsMgr::registerShortcut(const QString& theKeySequence)
185 {
186   if (theKeySequence.isEmpty()) {
187     return QKeySequence();
188   }
189   QKeySequence aResult(theKeySequence);
190   registerShortcut(aResult);
191   return aResult;
192 }
193
194 void XGUI_ActionsMgr::processEvent(const std::shared_ptr<Events_Message>& theMessage)
195 {
196   const Events_ID kResponseEvent =
197       Events_Loop::loop()->eventByName(EVENT_FEATURE_STATE_RESPONSE);
198   if (theMessage->eventID() == kResponseEvent) {
199     std::shared_ptr<ModelAPI_FeatureStateMessage> aStateMessage =
200         std::dynamic_pointer_cast<ModelAPI_FeatureStateMessage>(theMessage);
201     if (!aStateMessage.get())
202       return;
203     std::list<std::string> aFeaturesList = aStateMessage->features();
204     std::list<std::string>::iterator it = aFeaturesList.begin();
205     for( ; it != aFeaturesList.end(); ++it) {
206       QString anActionId = QString::fromStdString(*it);
207       bool theDefaultState = false;
208       if (myActions.contains(anActionId)) {
209         theDefaultState = myActions[anActionId]->isEnabled();
210       }
211       setActionEnabled(anActionId, aStateMessage->state(*it, theDefaultState));
212     }
213   } else if (theMessage.get()) {
214     #ifdef _DEBUG
215     std::cout << "XGUI_ActionsMgr::processEvent: unhandled message caught: " << std::endl
216               << theMessage->eventID().eventText() << std::endl;
217     #endif
218   }
219 }
220
221 QAction* XGUI_ActionsMgr::operationStateAction(OperationStateActionId theId, QObject* theParent)
222 {
223   QAction* aResult = NULL;
224   if (myOperationActions.contains(theId)) {
225     aResult = myOperationActions.value(theId);
226     if (theParent && aResult->parent() != theParent) {
227       aResult->setParent(theParent);
228     }
229   } else {
230     switch (theId) {
231       case Accept:
232       case AcceptAll:
233         aResult = new QAction(QIcon(":pictures/button_ok.png"), "", theParent);
234         break;
235       case Abort:
236       case AbortAll: {
237         aResult = new QAction(QIcon(":pictures/button_cancel.png"), "", theParent);
238         if(theId == Abort) {
239           aResult->setShortcut(QKeySequence(Qt::Key_Escape));
240         }
241       }
242       break;
243       case Help:
244         aResult = new QAction(QIcon(":pictures/button_help.png"), "", theParent);
245         break;
246       default:
247         break;
248     }
249     myOperationActions.insert(theId, aResult);
250   }
251   return aResult;
252 }
253
254 QAction* XGUI_ActionsMgr::action(const QString& theId)
255 {
256   QAction* anAction = 0;
257   if(myActions.contains(theId)) {
258     anAction = myActions.value(theId);
259   }
260   return anAction;
261 }
262
263 ActionInfo XGUI_ActionsMgr::actionInfoById(const QString& theId)
264 {
265   ActionInfo aResult;
266   if(myActions.contains(theId)) {
267     aResult.initFrom(myActions.value(theId));
268   } else {
269    aResult.id = theId;
270    aResult.text = theId;
271   }
272   return aResult;
273 }
274
275 void XGUI_ActionsMgr::setAllEnabled(bool isEnabled)
276 {
277   foreach(QString eachAction, myActions.keys())
278   {
279     setActionEnabled(eachAction, isEnabled);
280   }
281 }
282
283
284 //!
285 void XGUI_ActionsMgr::setNestedCommandsEnabled(bool theEnabled, const QString& theParent)
286 {
287   QStringList ltNestedActions;
288   if (theParent.isEmpty()) {  //Disable ALL nested
289     foreach(QString eachParent, myNestedActions.keys()) {
290       ltNestedActions << myNestedActions[eachParent];
291     }
292   } else {
293     ltNestedActions << myNestedActions[theParent];
294   }
295   foreach(QString eachNested, ltNestedActions) {
296     setActionEnabled(eachNested, theEnabled);
297   }
298 }
299
300 void XGUI_ActionsMgr::setNestedStackEnabled(ModuleBase_Operation* theOperation)
301 {
302   ModuleBase_OperationFeature* anOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
303   if(!anOperation || !anOperation->feature())
304     return;
305   FeaturePtr aFeature = anOperation->feature();
306   QString aFeatureId = QString::fromStdString(aFeature->getKind());
307   setActionEnabled(aFeatureId, true);
308   setNestedCommandsEnabled(true, aFeatureId);
309
310   setNestedStackEnabled(myOperationMgr->previousOperation(theOperation));
311 }
312
313 void XGUI_ActionsMgr::setActionChecked(const QString& theId, const bool theChecked)
314 {
315   if (myActions.contains(theId)) {
316     QAction* anAction = myActions[theId];
317     if (anAction->isCheckable()) {
318       anAction->setChecked(theChecked);
319     }
320   }
321 }
322
323 void XGUI_ActionsMgr::setActionEnabled(const QString& theId, const bool theEnabled)
324 {
325   if (myActions.contains(theId)) {
326     myActions[theId]->setEnabled(theEnabled);
327   }
328 }
329
330 /*
331  * Disables all actions which have the Document Kind different to
332  * the current document's kind
333  */
334 void XGUI_ActionsMgr::updateByDocumentKind()
335 {
336   std::string aStdDocKind = ModelAPI_Session::get()->activeDocument()->kind();
337   QString aDocKind = QString::fromStdString(aStdDocKind);
338   XGUI_Workshop* aWorkshop = static_cast<XGUI_Workshop*>(parent());
339   foreach(QAction* eachAction, myActions.values()) {
340     AppElements_Command* aCmd = dynamic_cast<AppElements_Command*>(eachAction);
341     QString aCmdDocKind;
342     if(aCmd) {
343       aCmdDocKind = aCmd->documentKind();
344     } else {
345       QString aId = eachAction->data().toString();
346       if (!aId.isEmpty()) {
347         aCmdDocKind = aWorkshop->salomeConnector()->documentKind(aId);
348       }
349     }
350     if(!aCmdDocKind.isEmpty() && aCmdDocKind != aDocKind) {
351       eachAction->setEnabled(false);
352     }
353   }
354 }
355
356 void XGUI_ActionsMgr::updateByPlugins(FeaturePtr anActiveFeature)
357 {
358   static Events_ID aStateRequestEventId = Events_Loop::loop()->eventByName(
359       EVENT_FEATURE_STATE_REQUEST);
360   std::shared_ptr<ModelAPI_FeatureStateMessage> aMsg(
361       new ModelAPI_FeatureStateMessage(aStateRequestEventId, this));
362   aMsg->setFeature(anActiveFeature);
363   Events_Loop::loop()->send(aMsg, false);
364 }