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);
260 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_cancel.png"), "Cancel",
265 aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_help.png"), "Help",
270 aResult = ModuleBase_Tools::createAction(QIcon(), tr("See preview"),
271 aParent, 0, 0, "Compute preview");
272 aResult->setStatusTip(aResult->toolTip());
278 myOperationActions.insert(theId, aResult);
283 QAction* XGUI_ActionsMgr::action(const QString& theId)
285 QAction* anAction = 0;
286 if(myActions.contains(theId)) {
287 anAction = myActions.value(theId);
292 ActionInfo XGUI_ActionsMgr::actionInfoById(const QString& theId)
295 if(myActions.contains(theId)) {
296 aResult.initFrom(myActions.value(theId));
299 aResult.text = theId;
304 void XGUI_ActionsMgr::setAllEnabled()
306 foreach(QString eachAction, myActions.keys()) {
307 if (myActions.contains(eachAction)) {
308 QAction* aAction = myActions[eachAction];
309 aAction->setEnabled(true);
316 void XGUI_ActionsMgr::setNestedCommandsEnabled(bool theEnabled, const QString& theParent)
318 QStringList ltNestedActions;
319 if (theParent.isEmpty()) { //Disable ALL nested
320 foreach(QString eachParent, myNestedActions.keys()) {
321 ltNestedActions << myNestedActions[eachParent];
324 ltNestedActions << myNestedActions[theParent];
326 foreach(QString eachNested, ltNestedActions) {
327 setActionEnabled(eachNested, theEnabled);
331 void XGUI_ActionsMgr::setNestedStackEnabled(ModuleBase_Operation* theOperation)
333 ModuleBase_OperationFeature* anOperation =
334 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
335 if(!anOperation || !anOperation->feature())
337 FeaturePtr aFeature = anOperation->feature();
338 QString aFeatureId = QString::fromStdString(aFeature->getKind());
339 //setActionEnabled(aFeatureId, true);
340 setNestedCommandsEnabled(true, aFeatureId);
342 setNestedStackEnabled(myOperationMgr->previousOperation(theOperation));
345 QStringList XGUI_ActionsMgr::allNestedCommands(ModuleBase_Operation* theOperation)
347 QStringList aFeatures;
348 ModuleBase_OperationFeature* anOperation =
349 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
350 if(!anOperation || !anOperation->feature())
352 FeaturePtr aFeature = anOperation->feature();
353 QString aFeatureId = QString::fromStdString(aFeature->getKind());
355 aFeatures << myNestedActions[aFeatureId];
356 aFeatures << allNestedCommands(myOperationMgr->previousOperation(theOperation));
360 void XGUI_ActionsMgr::setActionChecked(const QString& theId, const bool theChecked)
362 if (myActions.contains(theId)) {
363 QAction* anAction = myActions[theId];
364 if (anAction->isCheckable()) {
365 anAction->setChecked(theChecked);
370 void XGUI_ActionsMgr::setActionEnabled(const QString& theId, const bool theEnabled)
372 if (myActions.contains(theId)) {
373 QAction* aAction = myActions[theId];
374 // Initially all actions are enabled
375 // If it was disabled for any reason then we can not enable it
376 if (aAction->isEnabled())
377 aAction->setEnabled(theEnabled);
382 * Disables all actions which have the Document Kind different to
383 * the current document's kind
385 void XGUI_ActionsMgr::updateByDocumentKind()
387 std::string aStdDocKind = ModelAPI_Session::get()->activeDocument()->kind();
388 QString aDocKind = QString::fromStdString(aStdDocKind);
389 XGUI_Workshop* aWorkshop = static_cast<XGUI_Workshop*>(parent());
390 foreach(QAction* eachAction, myActions.values()) {
393 QString aId = eachAction->data().toString();
394 if (!aId.isEmpty()) {
395 aCmdDocKind = QString::fromStdString(
396 aWorkshop->salomeConnector()->featureInfo(aId)->documentKind());
399 AppElements_Command* aCmd = dynamic_cast<AppElements_Command*>(eachAction);
400 aCmdDocKind = QString::fromStdString(aCmd->featureMessage()->documentKind());
402 if(!aCmdDocKind.isEmpty() && aCmdDocKind != aDocKind) {
403 eachAction->setEnabled(false);
408 void XGUI_ActionsMgr::updateByPlugins(FeaturePtr anActiveFeature)
410 static Events_ID aStateRequestEventId = Events_Loop::loop()->eventByName(
411 EVENT_FEATURE_STATE_REQUEST);
412 std::shared_ptr<ModelAPI_FeatureStateMessage> aMsg(
413 new ModelAPI_FeatureStateMessage(aStateRequestEventId, this));
414 aMsg->setFeature(anActiveFeature);
415 Events_Loop::loop()->send(aMsg, false);