1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
22 #include <AppElements_Command.h>
25 #include <XGUI_ActionsMgr.h>
26 #include <XGUI_Workshop.h>
27 #include <XGUI_OperationMgr.h>
28 #include <XGUI_SalomeConnector.h>
29 #include <XGUI_Selection.h>
30 #include <XGUI_SelectionMgr.h>
32 #include <Events_Loop.h>
33 #include <Events_InfoMessage.h>
35 #include <ModelAPI_Session.h>
36 #include <ModelAPI_Events.h>
37 #include <ModelAPI_Validator.h>
38 #include <ModuleBase_Operation.h>
39 #include <ModuleBase_OperationFeature.h>
40 #include <ModuleBase_SelectionValidator.h>
41 #include <ModuleBase_Tools.h>
45 #include <QMainWindow>
52 XGUI_ActionsMgr::XGUI_ActionsMgr(XGUI_Workshop* theParent)
54 myWorkshop(theParent),
55 myOperationMgr(theParent->operationMgr())
58 myShortcuts << QKeySequence::Save;
59 myShortcuts << QKeySequence::Undo;
60 myShortcuts << QKeySequence::Redo;
61 myShortcuts << QKeySequence::Open;
62 myShortcuts << QKeySequence::Close;
64 //Initialize event listening
65 Events_Loop* aLoop = Events_Loop::loop();
66 static Events_ID aStateResponseEventId =
67 Events_Loop::loop()->eventByName(EVENT_FEATURE_STATE_RESPONSE);
68 aLoop->registerListener(this, aStateResponseEventId, NULL, true);
71 XGUI_ActionsMgr::~XGUI_ActionsMgr()
75 void XGUI_ActionsMgr::addCommand(QAction* theCmd)
77 QString aId = theCmd->data().toString();
81 myActions.insert(aId, theCmd);
83 XGUI_Workshop* aWorkshop = static_cast<XGUI_Workshop*>(parent());
84 const std::shared_ptr<Config_FeatureMessage>& anInfo =
85 aWorkshop->salomeConnector()->featureInfo(aId);
87 myNestedActions[aId] = QString::fromStdString(anInfo->nestedFeatures())
88 .split(" ", QString::SkipEmptyParts);
90 AppElements_Command* aXCmd = dynamic_cast<AppElements_Command*>(theCmd);
91 myNestedActions[aId] = aXCmd->nestedCommands();
95 void XGUI_ActionsMgr::addNestedCommands(const QString& theId, const QStringList& theCommands)
97 myNestedActions[theId] = theCommands;
100 QStringList XGUI_ActionsMgr::nestedCommands(const QString& theId) const
102 if (myNestedActions.contains(theId))
103 return myNestedActions[theId];
104 return QStringList();
107 bool XGUI_ActionsMgr::isNested(const QString& theId) const
109 foreach(QString aId, myNestedActions.keys())
111 QStringList aList = myNestedActions[aId];
112 if (aList.contains(theId))
118 void XGUI_ActionsMgr::updateCommandsStatus()
121 XGUI_Selection* aSelection = myWorkshop->selector()->selection();
122 if (aSelection->getSelected(ModuleBase_ISelection::AllControls).size() > 0)
123 updateOnViewSelection();
125 FeaturePtr anActiveFeature = FeaturePtr();
126 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
127 (myOperationMgr->currentOperation());
129 anActiveFeature = aFOperation->feature();
130 QStringList aNested = allNestedCommands(aFOperation);
131 foreach(QString aAction, myActions.keys()) {
132 if (!aNested.contains(aAction))
133 setActionEnabled(aAction, false);
136 setNestedCommandsEnabled(false);
138 updateByPlugins(anActiveFeature);
139 updateByDocumentKind();
143 void XGUI_ActionsMgr::updateCheckState()
145 QString eachCommand = QString();
146 foreach(eachCommand, myActions.keys()) {
147 setActionChecked(eachCommand, false);
149 QStringList ltActiveCommands = myOperationMgr->operationList();
150 foreach(eachCommand, ltActiveCommands) {
151 setActionChecked(eachCommand, true);
155 void XGUI_ActionsMgr::updateOnViewSelection()
157 if (!myOperationMgr->hasOperation())
160 QStringList aIdList = myOperationMgr->operationList();
161 //ModuleBase_Operation* anOperation = myOperationMgr->currentOperation();
162 //FeaturePtr anActiveFeature = anOperation->feature();
163 //if(!anActiveFeature.get())
164 if (aIdList.isEmpty())
167 ModuleBase_Operation* theOperation = myOperationMgr->currentOperation();
168 //QString aFeatureId = QString::fromStdString(anActiveFeature->getKind());
169 XGUI_Selection* aSelection = myWorkshop->selector()->selection();
170 // only viewer selection is processed
171 SessionPtr aMgr = ModelAPI_Session::get();
172 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
173 foreach(QString aFeatureId, aIdList) {
174 foreach(QString aId, nestedCommands(aFeatureId)) {
175 ModelAPI_ValidatorsFactory::Validators aValidators;
176 aFactory->validators(aId.toStdString(), aValidators);
177 ModelAPI_ValidatorsFactory::Validators::iterator aValidatorIt = aValidators.begin();
178 for (; aValidatorIt != aValidators.end(); ++aValidatorIt) {
179 const ModuleBase_SelectionValidator* aSelValidator =
180 dynamic_cast<const ModuleBase_SelectionValidator*>
181 (aFactory->validator(aValidatorIt->first));
183 setActionEnabled(aId, aSelValidator->isValid(aSelection, theOperation));
189 QKeySequence XGUI_ActionsMgr::registerShortcut(const QKeySequence& theKeySequence)
191 if (theKeySequence.isEmpty()) {
192 return QKeySequence();
194 if (myShortcuts.contains(theKeySequence)) {
195 QString aMessage = tr("Shortcut %1 is already defined. Ignore.");
196 aMessage = aMessage.arg(theKeySequence.toString());
197 Events_InfoMessage("XGUI_ActionsMgr", aMessage.toStdString()).send();
198 return QKeySequence();
200 myShortcuts.append(theKeySequence);
201 return theKeySequence;
204 QKeySequence XGUI_ActionsMgr::registerShortcut(const QString& theKeySequence)
206 if (theKeySequence.isEmpty()) {
207 return QKeySequence();
209 QKeySequence aResult(theKeySequence);
210 registerShortcut(aResult);
214 void XGUI_ActionsMgr::processEvent(const std::shared_ptr<Events_Message>& theMessage)
216 const Events_ID kResponseEvent =
217 Events_Loop::loop()->eventByName(EVENT_FEATURE_STATE_RESPONSE);
218 if (theMessage->eventID() == kResponseEvent) {
219 std::shared_ptr<ModelAPI_FeatureStateMessage> aStateMessage =
220 std::dynamic_pointer_cast<ModelAPI_FeatureStateMessage>(theMessage);
221 if (!aStateMessage.get())
223 std::list<std::string> aFeaturesList = aStateMessage->features();
224 std::list<std::string>::iterator it = aFeaturesList.begin();
225 for( ; it != aFeaturesList.end(); ++it) {
226 QString anActionId = QString::fromStdString(*it);
227 bool theDefaultState = false;
228 if (myActions.contains(anActionId)) {
229 theDefaultState = myActions[anActionId]->isEnabled();
231 setActionEnabled(anActionId, aStateMessage->state(*it, theDefaultState));
233 } else if (theMessage.get()) {
235 std::cout << "XGUI_ActionsMgr::processEvent: unhandled message caught: " << std::endl
236 << theMessage->eventID().eventText() << std::endl;
241 QAction* XGUI_ActionsMgr::operationStateAction(OperationStateActionId theId)
243 QAction* aResult = NULL;
244 if (myOperationActions.contains(theId)) {
245 aResult = myOperationActions.value(theId);
246 //if (theParent && aResult->parent() != theParent) {
247 // aResult->setParent(theParent);
250 QWidget* aParent = myWorkshop->desktop();
254 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_ok.png"),
255 "Apply" /*empty to show error*/, aParent);
259 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_ok-plus.png"),
260 "Apply and continue" /*empty to show error*/, aParent);
265 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_cancel.png"), "Cancel",
270 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_help.png"), "Help",
275 aResult = ModuleBase_Tools::createAction(QIcon(), tr("See preview"),
276 aParent, 0, 0, "Compute preview");
277 aResult->setStatusTip(aResult->toolTip());
283 myOperationActions.insert(theId, aResult);
288 QAction* XGUI_ActionsMgr::action(const QString& theId)
290 QAction* anAction = 0;
291 if(myActions.contains(theId)) {
292 anAction = myActions.value(theId);
297 ActionInfo XGUI_ActionsMgr::actionInfoById(const QString& theId)
300 if(myActions.contains(theId)) {
301 aResult.initFrom(myActions.value(theId));
304 aResult.text = theId;
309 void XGUI_ActionsMgr::setAllEnabled()
311 foreach(QString eachAction, myActions.keys()) {
312 if (myActions.contains(eachAction)) {
313 QAction* aAction = myActions[eachAction];
314 aAction->setEnabled(true);
321 void XGUI_ActionsMgr::setNestedCommandsEnabled(bool theEnabled, const QString& theParent)
323 QStringList ltNestedActions;
324 if (theParent.isEmpty()) { //Disable ALL nested
325 foreach(QString eachParent, myNestedActions.keys()) {
326 ltNestedActions << myNestedActions[eachParent];
329 ltNestedActions << myNestedActions[theParent];
331 foreach(QString eachNested, ltNestedActions) {
332 setActionEnabled(eachNested, theEnabled);
336 void XGUI_ActionsMgr::setNestedStackEnabled(ModuleBase_Operation* theOperation)
338 ModuleBase_OperationFeature* anOperation =
339 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
340 if(!anOperation || !anOperation->feature())
342 FeaturePtr aFeature = anOperation->feature();
343 QString aFeatureId = QString::fromStdString(aFeature->getKind());
344 //setActionEnabled(aFeatureId, true);
345 setNestedCommandsEnabled(true, aFeatureId);
347 setNestedStackEnabled(myOperationMgr->previousOperation(theOperation));
350 QStringList XGUI_ActionsMgr::allNestedCommands(ModuleBase_Operation* theOperation)
352 QStringList aFeatures;
353 ModuleBase_OperationFeature* anOperation =
354 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
355 if(!anOperation || !anOperation->feature())
357 FeaturePtr aFeature = anOperation->feature();
358 QString aFeatureId = QString::fromStdString(aFeature->getKind());
360 aFeatures << myNestedActions[aFeatureId];
361 aFeatures << allNestedCommands(myOperationMgr->previousOperation(theOperation));
365 void XGUI_ActionsMgr::setActionChecked(const QString& theId, const bool theChecked)
367 if (myActions.contains(theId)) {
368 QAction* anAction = myActions[theId];
369 if (anAction->isCheckable()) {
370 anAction->setChecked(theChecked);
375 void XGUI_ActionsMgr::setActionEnabled(const QString& theId, const bool theEnabled)
377 if (myActions.contains(theId)) {
378 QAction* aAction = myActions[theId];
379 // Initially all actions are enabled
380 // If it was disabled for any reason then we can not enable it
381 if (aAction->isEnabled())
382 aAction->setEnabled(theEnabled);
387 * Disables all actions which have the Document Kind different to
388 * the current document's kind
390 void XGUI_ActionsMgr::updateByDocumentKind()
392 std::string aStdDocKind = ModelAPI_Session::get()->activeDocument()->kind();
393 QString aDocKind = QString::fromStdString(aStdDocKind);
394 XGUI_Workshop* aWorkshop = static_cast<XGUI_Workshop*>(parent());
395 foreach(QAction* eachAction, myActions.values()) {
398 QString aId = eachAction->data().toString();
399 if (!aId.isEmpty()) {
400 aCmdDocKind = QString::fromStdString(
401 aWorkshop->salomeConnector()->featureInfo(aId)->documentKind());
404 AppElements_Command* aCmd = dynamic_cast<AppElements_Command*>(eachAction);
405 aCmdDocKind = QString::fromStdString(aCmd->featureMessage()->documentKind());
407 if(!aCmdDocKind.isEmpty() && aCmdDocKind != aDocKind) {
408 eachAction->setEnabled(false);
413 void XGUI_ActionsMgr::updateByPlugins(FeaturePtr anActiveFeature)
415 static Events_ID aStateRequestEventId = Events_Loop::loop()->eventByName(
416 EVENT_FEATURE_STATE_REQUEST);
417 std::shared_ptr<ModelAPI_FeatureStateMessage> aMsg(
418 new ModelAPI_FeatureStateMessage(aStateRequestEventId, this));
419 aMsg->setFeature(anActiveFeature);
420 Events_Loop::loop()->send(aMsg, false);