1 // Copyright (C) 2014-2019 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 email : webmaster.salome@opencascade.com
21 #include <AppElements_Command.h>
24 #include <XGUI_ActionsMgr.h>
25 #include <XGUI_Workshop.h>
26 #include <XGUI_OperationMgr.h>
27 #include <XGUI_SalomeConnector.h>
28 #include <XGUI_Selection.h>
29 #include <XGUI_SelectionMgr.h>
31 #include <Events_Loop.h>
32 #include <Events_InfoMessage.h>
34 #include <ModelAPI_Session.h>
35 #include <ModelAPI_Events.h>
36 #include <ModelAPI_Validator.h>
37 #include <ModuleBase_Operation.h>
38 #include <ModuleBase_OperationFeature.h>
39 #include <ModuleBase_SelectionValidator.h>
40 #include <ModuleBase_Tools.h>
44 #include <QMainWindow>
51 XGUI_ActionsMgr::XGUI_ActionsMgr(XGUI_Workshop* theParent)
53 myWorkshop(theParent),
54 myOperationMgr(theParent->operationMgr())
57 myShortcuts << QKeySequence::Save;
58 myShortcuts << QKeySequence::Undo;
59 myShortcuts << QKeySequence::Redo;
60 myShortcuts << QKeySequence::Open;
61 myShortcuts << QKeySequence::Close;
63 //Initialize event listening
64 Events_Loop* aLoop = Events_Loop::loop();
65 static Events_ID aStateResponseEventId =
66 Events_Loop::loop()->eventByName(EVENT_FEATURE_STATE_RESPONSE);
67 aLoop->registerListener(this, aStateResponseEventId, NULL, true);
70 XGUI_ActionsMgr::~XGUI_ActionsMgr()
74 void XGUI_ActionsMgr::addCommand(QAction* theCmd)
76 QString aId = theCmd->data().toString();
80 myActions.insert(aId, theCmd);
82 XGUI_Workshop* aWorkshop = static_cast<XGUI_Workshop*>(parent());
83 const std::shared_ptr<Config_FeatureMessage>& anInfo =
84 aWorkshop->salomeConnector()->featureInfo(aId);
86 myNestedActions[aId] = QString::fromStdString(anInfo->nestedFeatures())
87 .split(" ", QString::SkipEmptyParts);
89 AppElements_Command* aXCmd = dynamic_cast<AppElements_Command*>(theCmd);
90 myNestedActions[aId] = aXCmd->nestedCommands();
94 void XGUI_ActionsMgr::addNestedCommands(const QString& theId, const QStringList& theCommands)
96 myNestedActions[theId] = theCommands;
99 QStringList XGUI_ActionsMgr::nestedCommands(const QString& theId) const
101 if (myNestedActions.contains(theId))
102 return myNestedActions[theId];
103 return QStringList();
106 bool XGUI_ActionsMgr::isNested(const QString& theId) const
108 foreach(QString aId, myNestedActions.keys())
110 QStringList aList = myNestedActions[aId];
111 if (aList.contains(theId))
117 void XGUI_ActionsMgr::updateCommandsStatus()
120 XGUI_Selection* aSelection = myWorkshop->selector()->selection();
121 if (aSelection->getSelected(ModuleBase_ISelection::AllControls).size() > 0)
122 updateOnViewSelection();
124 FeaturePtr anActiveFeature = FeaturePtr();
125 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
126 (myOperationMgr->currentOperation());
128 anActiveFeature = aFOperation->feature();
129 QStringList aNested = allNestedCommands(aFOperation);
130 foreach(QString aAction, myActions.keys()) {
131 if (!aNested.contains(aAction))
132 setActionEnabled(aAction, false);
135 setNestedCommandsEnabled(false);
137 updateByPlugins(anActiveFeature);
138 updateByDocumentKind();
142 void XGUI_ActionsMgr::updateCheckState()
144 QString eachCommand = QString();
145 foreach(eachCommand, myActions.keys()) {
146 setActionChecked(eachCommand, false);
148 QStringList ltActiveCommands = myOperationMgr->operationList();
149 foreach(eachCommand, ltActiveCommands) {
150 setActionChecked(eachCommand, true);
154 void XGUI_ActionsMgr::updateOnViewSelection()
156 if (!myOperationMgr->hasOperation())
159 QStringList aIdList = myOperationMgr->operationList();
160 //ModuleBase_Operation* anOperation = myOperationMgr->currentOperation();
161 //FeaturePtr anActiveFeature = anOperation->feature();
162 //if(!anActiveFeature.get())
163 if (aIdList.isEmpty())
166 ModuleBase_Operation* theOperation = myOperationMgr->currentOperation();
167 //QString aFeatureId = QString::fromStdString(anActiveFeature->getKind());
168 XGUI_Selection* aSelection = myWorkshop->selector()->selection();
169 // only viewer selection is processed
170 SessionPtr aMgr = ModelAPI_Session::get();
171 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
172 foreach(QString aFeatureId, aIdList) {
173 foreach(QString aId, nestedCommands(aFeatureId)) {
174 ModelAPI_ValidatorsFactory::Validators aValidators;
175 aFactory->validators(aId.toStdString(), aValidators);
176 ModelAPI_ValidatorsFactory::Validators::iterator aValidatorIt = aValidators.begin();
177 for (; aValidatorIt != aValidators.end(); ++aValidatorIt) {
178 const ModuleBase_SelectionValidator* aSelValidator =
179 dynamic_cast<const ModuleBase_SelectionValidator*>
180 (aFactory->validator(aValidatorIt->first));
182 setActionEnabled(aId, aSelValidator->isValid(aSelection, theOperation));
188 QKeySequence XGUI_ActionsMgr::registerShortcut(const QKeySequence& theKeySequence)
190 if (theKeySequence.isEmpty()) {
191 return QKeySequence();
193 if (myShortcuts.contains(theKeySequence)) {
194 QString aMessage = tr("Shortcut %1 is already defined. Ignore.");
195 aMessage = aMessage.arg(theKeySequence.toString());
196 Events_InfoMessage("XGUI_ActionsMgr", aMessage.toStdString()).send();
197 return QKeySequence();
199 myShortcuts.append(theKeySequence);
200 return theKeySequence;
203 QKeySequence XGUI_ActionsMgr::registerShortcut(const QString& theKeySequence)
205 if (theKeySequence.isEmpty()) {
206 return QKeySequence();
208 QKeySequence aResult(theKeySequence);
209 registerShortcut(aResult);
213 void XGUI_ActionsMgr::processEvent(const std::shared_ptr<Events_Message>& theMessage)
215 const Events_ID kResponseEvent =
216 Events_Loop::loop()->eventByName(EVENT_FEATURE_STATE_RESPONSE);
217 if (theMessage->eventID() == kResponseEvent) {
218 std::shared_ptr<ModelAPI_FeatureStateMessage> aStateMessage =
219 std::dynamic_pointer_cast<ModelAPI_FeatureStateMessage>(theMessage);
220 if (!aStateMessage.get())
222 std::list<std::string> aFeaturesList = aStateMessage->features();
223 std::list<std::string>::iterator it = aFeaturesList.begin();
224 for( ; it != aFeaturesList.end(); ++it) {
225 QString anActionId = QString::fromStdString(*it);
226 bool theDefaultState = false;
227 if (myActions.contains(anActionId)) {
228 theDefaultState = myActions[anActionId]->isEnabled();
230 setActionEnabled(anActionId, aStateMessage->state(*it, theDefaultState));
232 } else if (theMessage.get()) {
234 std::cout << "XGUI_ActionsMgr::processEvent: unhandled message caught: " << std::endl
235 << theMessage->eventID().eventText() << std::endl;
240 QAction* XGUI_ActionsMgr::operationStateAction(OperationStateActionId theId)
242 QAction* aResult = NULL;
243 if (myOperationActions.contains(theId)) {
244 aResult = myOperationActions.value(theId);
245 //if (theParent && aResult->parent() != theParent) {
246 // aResult->setParent(theParent);
249 QWidget* aParent = myWorkshop->desktop();
253 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_ok.png"),
254 tr("Apply"), aParent);
258 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_ok-plus.png"),
259 tr("Apply and continue"), aParent);
264 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_cancel.png"), tr("Cancel"),
269 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_help.png"), tr("Help"),
274 aResult = ModuleBase_Tools::createAction(QIcon(), tr("See preview"),
275 aParent, 0, 0, tr("Compute preview"));
276 aResult->setStatusTip(aResult->toolTip());
282 myOperationActions.insert(theId, aResult);
287 QAction* XGUI_ActionsMgr::action(const QString& theId)
289 QAction* anAction = 0;
290 if(myActions.contains(theId)) {
291 anAction = myActions.value(theId);
296 ActionInfo XGUI_ActionsMgr::actionInfoById(const QString& theId)
299 if(myActions.contains(theId)) {
300 aResult.initFrom(myActions.value(theId));
303 aResult.text = theId;
308 void XGUI_ActionsMgr::setAllEnabled()
310 foreach(QString eachAction, myActions.keys()) {
311 if (myActions.contains(eachAction)) {
312 QAction* aAction = myActions[eachAction];
313 aAction->setEnabled(true);
320 void XGUI_ActionsMgr::setNestedCommandsEnabled(bool theEnabled, const QString& theParent)
322 QStringList ltNestedActions;
323 if (theParent.isEmpty()) { //Disable ALL nested
324 foreach(QString eachParent, myNestedActions.keys()) {
325 ltNestedActions << myNestedActions[eachParent];
328 ltNestedActions << myNestedActions[theParent];
330 foreach(QString eachNested, ltNestedActions) {
331 setActionEnabled(eachNested, theEnabled);
335 void XGUI_ActionsMgr::setNestedStackEnabled(ModuleBase_Operation* theOperation)
337 ModuleBase_OperationFeature* anOperation =
338 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
339 if(!anOperation || !anOperation->feature())
341 FeaturePtr aFeature = anOperation->feature();
342 QString aFeatureId = QString::fromStdString(aFeature->getKind());
343 //setActionEnabled(aFeatureId, true);
344 setNestedCommandsEnabled(true, aFeatureId);
346 setNestedStackEnabled(myOperationMgr->previousOperation(theOperation));
349 QStringList XGUI_ActionsMgr::allNestedCommands(ModuleBase_Operation* theOperation)
351 QStringList aFeatures;
352 ModuleBase_OperationFeature* anOperation =
353 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
354 if(!anOperation || !anOperation->feature())
356 FeaturePtr aFeature = anOperation->feature();
357 QString aFeatureId = QString::fromStdString(aFeature->getKind());
359 aFeatures << myNestedActions[aFeatureId];
360 aFeatures << allNestedCommands(myOperationMgr->previousOperation(theOperation));
364 void XGUI_ActionsMgr::setActionChecked(const QString& theId, const bool theChecked)
366 if (myActions.contains(theId)) {
367 QAction* anAction = myActions[theId];
368 if (anAction->isCheckable()) {
369 anAction->setChecked(theChecked);
374 void XGUI_ActionsMgr::setActionEnabled(const QString& theId, const bool theEnabled)
376 if (myActions.contains(theId)) {
377 QAction* aAction = myActions[theId];
378 // Initially all actions are enabled
379 // If it was disabled for any reason then we can not enable it
380 if (aAction->isEnabled())
381 aAction->setEnabled(theEnabled);
386 * Disables all actions which have the Document Kind different to
387 * the current document's kind
389 void XGUI_ActionsMgr::updateByDocumentKind()
391 std::string aStdDocKind = ModelAPI_Session::get()->activeDocument()->kind();
392 QString aDocKind = QString::fromStdString(aStdDocKind);
393 XGUI_Workshop* aWorkshop = static_cast<XGUI_Workshop*>(parent());
394 foreach(QAction* eachAction, myActions.values()) {
397 QString aId = eachAction->data().toString();
398 if (!aId.isEmpty()) {
399 aCmdDocKind = QString::fromStdString(
400 aWorkshop->salomeConnector()->featureInfo(aId)->documentKind());
403 AppElements_Command* aCmd = dynamic_cast<AppElements_Command*>(eachAction);
404 aCmdDocKind = QString::fromStdString(aCmd->featureMessage()->documentKind());
406 if(!aCmdDocKind.isEmpty() && aCmdDocKind != aDocKind) {
407 eachAction->setEnabled(false);
412 void XGUI_ActionsMgr::updateByPlugins(FeaturePtr anActiveFeature)
414 static Events_ID aStateRequestEventId = Events_Loop::loop()->eventByName(
415 EVENT_FEATURE_STATE_REQUEST);
416 std::shared_ptr<ModelAPI_FeatureStateMessage> aMsg(
417 new ModelAPI_FeatureStateMessage(aStateRequestEventId, this));
418 aMsg->setFeature(anActiveFeature);
419 Events_Loop::loop()->send(aMsg, false);