From: sbh Date: Thu, 22 May 2014 17:01:20 +0000 (+0400) Subject: Improved command state processing in ActionMgr. Fixes #41 #36 X-Git-Tag: V_0.2~27 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=a993a2e680b4a5a2e8b9ad9c998dc872ff962702;p=modules%2Fshaper.git Improved command state processing in ActionMgr. Fixes #41 #36 --- diff --git a/src/ModuleBase/ModuleBase_Operation.cpp b/src/ModuleBase/ModuleBase_Operation.cpp index e742c0553..31fce0718 100644 --- a/src/ModuleBase/ModuleBase_Operation.cpp +++ b/src/ModuleBase/ModuleBase_Operation.cpp @@ -29,11 +29,21 @@ ModuleBase_Operation::~ModuleBase_Operation() { } +QString ModuleBase_Operation::id() const +{ + return getDescription()->operationId(); +} + boost::shared_ptr ModuleBase_Operation::feature() const { return myFeature; } +bool ModuleBase_Operation::isNestedOperationsEnabled() +{ + return true; +} + void ModuleBase_Operation::storeReal(double theValue) { if(!myFeature){ diff --git a/src/ModuleBase/ModuleBase_Operation.h b/src/ModuleBase/ModuleBase_Operation.h index 43c225dd1..f15bddeb9 100644 --- a/src/ModuleBase/ModuleBase_Operation.h +++ b/src/ModuleBase/ModuleBase_Operation.h @@ -48,10 +48,14 @@ public: /// Destructor virtual ~ModuleBase_Operation(); + // Returns operations Id from it's description + QString id() const; /// Returns the operation feature /// \return the feature boost::shared_ptr feature() const; + virtual bool isNestedOperationsEnabled(); + // Data model methods. /// Stores a real value in model. /// \param theValue - to store diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index b54dc192a..d052adf9e 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -164,7 +164,7 @@ void PartSet_Module::onKeyRelease(QKeyEvent* theEvent) void PartSet_Module::onPlaneSelected(double theX, double theY, double theZ) { myWorkshop->viewer()->setViewProjection(theX, theY, theZ); - myWorkshop->actionsMgr()->setNestedActionsEnabled(true); + myWorkshop->actionsMgr()->update(); } void PartSet_Module::onLaunchOperation(std::string theName, boost::shared_ptr theFeature) @@ -176,7 +176,7 @@ void PartSet_Module::onLaunchOperation(std::string theName, boost::shared_ptr aPresentations = myWorkshop->displayer()->GetViewerPrs(); aPreviewOp->init(theFeature, aPresentations); } - myWorkshop->actionsMgr()->setActionChecked(anOperation->getDescription()->operationId(), true); + myWorkshop->actionsMgr()->updateCheckState(); sendOperation(anOperation); } diff --git a/src/XGUI/XGUI_ActionsMgr.cpp b/src/XGUI/XGUI_ActionsMgr.cpp index 7f0b02d9a..6815d81d3 100644 --- a/src/XGUI/XGUI_ActionsMgr.cpp +++ b/src/XGUI/XGUI_ActionsMgr.cpp @@ -5,15 +5,21 @@ #include "XGUI_ActionsMgr.h" #include "XGUI_Command.h" #include "XGUI_Workshop.h" -#include "XGUI_SalomeConnector.h" +#include "XGUI_OperationMgr.h" + +#include #include +#ifdef _DEBUG +#include +#endif + XGUI_ActionsMgr::XGUI_ActionsMgr(XGUI_Workshop* theParent) - : QObject(theParent), myWorkshop(theParent) + : QObject(theParent), myOperationMgr(theParent->operationMgr()) { - + } XGUI_ActionsMgr::~XGUI_ActionsMgr() @@ -24,79 +30,85 @@ XGUI_ActionsMgr::~XGUI_ActionsMgr() void XGUI_ActionsMgr::addCommand(QAction* theCmd) { QString aId = theCmd->data().toString(); + if(aId.isEmpty()) { + return; + } myActions.insert(aId, theCmd); - myActionsState.insert(aId, theCmd->isEnabled()); - connect(theCmd, SIGNAL(triggered(bool)), this, SLOT(setActionsDisabled(bool))); + XGUI_Command* aXCmd = dynamic_cast(theCmd); + if (aXCmd) { + myNestedActions[aId] = aXCmd->nestedCommands(); + } } -void XGUI_ActionsMgr::setActionsDisabled(bool isDisabled) +void XGUI_ActionsMgr::addNestedCommands(const QString& theId, const QStringList& theCommands) { - //Re-enable actions (just restore their state) - if (!isDisabled) { - myNestedActions.clear(); - restoreCommandState(); - return; - } - //Disable all actions, but caller and unblockable (defined in a xml) - saveCommandsState(); - - QString aSkippedId; - QAction* aToggledFeature = dynamic_cast(sender()); - aSkippedId = aToggledFeature->data().toString(); + myNestedActions[theId] = theCommands; +} - QStringList anActionIdsList = myActions.keys(); - foreach(QString eachKey, anActionIdsList) { - if (eachKey == aSkippedId) { - continue; - } - myActions[eachKey]->setEnabled(false); - } - if (myWorkshop->isSalomeMode()) { - myNestedActions = myWorkshop->salomeConnector()->nestedActions(aSkippedId); +void XGUI_ActionsMgr::update() +{ + if(myOperationMgr->hasOperation()) { + setAllEnabled(false); + ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); + QString anOperationId = anOperation->id(); + setActionEnabled(anOperationId, true); + bool isNestedEnabled = anOperation->isNestedOperationsEnabled(); + setNestedCommandsEnabled(isNestedEnabled, anOperationId); } else { - XGUI_Command* aToggledFeature = dynamic_cast(sender()); - myNestedActions = aToggledFeature->unblockableCommands(); + setAllEnabled(true); + setNestedCommandsEnabled(false); } + updateCheckState(); } -void XGUI_ActionsMgr::saveCommandsState() +void XGUI_ActionsMgr::setAllEnabled(bool isEnabled) { - myActionsState.clear(); - QStringList anActionIdsList = myActions.keys(); - foreach(QString eachKey, anActionIdsList) { - myActionsState.insert(eachKey, myActions[eachKey]->isEnabled()); + foreach(QString eachAction, myActions.keys()) { + setActionEnabled(eachAction, isEnabled); } - } -void XGUI_ActionsMgr::restoreCommandState() +//! +void XGUI_ActionsMgr::setNestedCommandsEnabled(bool theEnabled, const QString& theParent) { - QStringList anActionIdsList = myActions.keys(); - foreach(QString eachKey, anActionIdsList) { - myActions[eachKey]->setEnabled(myActionsState[eachKey]); - myActions[eachKey]->setChecked(false); + QStringList ltNestedActions; + if(theParent.isEmpty()) { //Disable ALL nested + foreach(QString eachParent, myNestedActions.keys()) { + ltNestedActions << myNestedActions[eachParent]; + } + } else { + ltNestedActions << myNestedActions[theParent]; + } + foreach(QString eachNested, ltNestedActions) { + setActionEnabled(eachNested, theEnabled); } } void XGUI_ActionsMgr::setActionChecked(const QString& theId, const bool theChecked) { - if(myActions.contains(theId)) { - myActions[theId]->setChecked(theChecked); + QAction* anAction = myActions[theId]; + if(anAction && anAction->isCheckable()) { + anAction->setChecked(theChecked); } } -void XGUI_ActionsMgr::updateAction(const QString& theId) + +void XGUI_ActionsMgr::setActionEnabled(const QString& theId, const bool theEnabled) { - if(myActions.contains(theId)){ - myActions[theId]->setEnabled(myActionsState[theId]); - myActions[theId]->setChecked(false); + QAction* anAction = myActions[theId]; + if(anAction) { + anAction->setEnabled(theEnabled); } } -void XGUI_ActionsMgr::setNestedActionsEnabled(bool isEnabled) +void XGUI_ActionsMgr::updateCheckState() { - foreach(QString eachKey, myNestedActions) { - if (myActions.contains(eachKey)) - myActions[eachKey]->setEnabled(isEnabled); + QString eachCommand = QString(); + foreach(eachCommand, myActions.keys()) { + setActionChecked(eachCommand, false); + } + QStringList ltActiveCommands = myOperationMgr->operationList(); + foreach(eachCommand, ltActiveCommands) { + setActionChecked(eachCommand, true); } } diff --git a/src/XGUI/XGUI_ActionsMgr.h b/src/XGUI/XGUI_ActionsMgr.h index 3390a83f3..38b8e167d 100644 --- a/src/XGUI/XGUI_ActionsMgr.h +++ b/src/XGUI/XGUI_ActionsMgr.h @@ -13,6 +13,7 @@ class XGUI_Command; class XGUI_Workshop; +class XGUI_OperationMgr; class QAction; class XGUI_EXPORT XGUI_ActionsMgr: public QObject @@ -20,32 +21,42 @@ class XGUI_EXPORT XGUI_ActionsMgr: public QObject Q_OBJECT public: - XGUI_ActionsMgr(XGUI_Workshop* theParent); + XGUI_ActionsMgr(XGUI_Workshop* theWorkshop); virtual ~XGUI_ActionsMgr(); - + //! Add a command in the manager. + //! Please note that nested commands in the Salome mode (No XGUI_Command, pure QActions) + //! won't be extracted and should be added manually using the addNestedCommands method. void addCommand(QAction* theCmd); - - void saveCommandsState(); - void restoreCommandState(); - - /// Set the action is checked - /// \param theId - string ID of the command - /// \praram theChecked - the new checked state - void setActionChecked(const QString& theId, const bool theChecked); - - void updateAction(const QString&); - void setNestedActionsEnabled(bool); + //! Sets relation between the command (with given Id) and it's nested actions. + void addNestedCommands(const QString& theId, const QStringList& theCommands); public slots: - void setActionsDisabled(bool isEnabled); + //! Update workbench actions according to OperationMgr state: + //! No active operations: all actions but nested are available + //! There is active operation: current operation + it's nested + //! are enabled, all the rest is disabled. All active commands is checked. + void update(); + //! Sets all commands checked if it's operation is active. + void updateCheckState(); + +protected: + //! Sets all actions to isEnabled state. + void setAllEnabled(bool isEnabled); + //! Sets all nested actions to isEnabled state for the command with given ID. + //! If ID is empty - all nested actions will be affected. + void setNestedCommandsEnabled(bool isEnabled, const QString& theParent = QString()); + //! Sets the action with theId to theChecked state. + void setActionChecked(const QString& theId, const bool theChecked); + //! Sets the action with theId to theEnabled state. + void setActionEnabled(const QString& theId, const bool theEnabled); private: - QStringList myNestedActions; QMap myActions; - QMap myActionsState; + QMap myNestedActions; - XGUI_Workshop* myWorkshop; + XGUI_OperationMgr* myOperationMgr; }; #endif /* XGUI_ACTIONSMGR_H_ */ + diff --git a/src/XGUI/XGUI_Command.cpp b/src/XGUI/XGUI_Command.cpp index 220e04f47..0ddb0ecfc 100644 --- a/src/XGUI/XGUI_Command.cpp +++ b/src/XGUI/XGUI_Command.cpp @@ -38,6 +38,7 @@ QWidget* XGUI_Command::createWidget(QWidget* theParent) aButton->addAction(this); connect(aButton, SIGNAL(clicked()), this, SLOT(trigger())); connect(this, SIGNAL(toggled(bool)), aButton, SLOT(setChecked(bool))); + connect(this, SIGNAL(toggled(bool)), aButton, SLOT(setChecked(bool))); aButton->setFlat(true); aButton->setCheckable(myCheckable); this->setCheckable(myCheckable); @@ -53,12 +54,12 @@ void XGUI_Command::connectTo(const QObject* theResiver, const char* theSlot) connect(this, SIGNAL(triggered(bool)), theResiver, theSlot); } -const QStringList& XGUI_Command::unblockableCommands() const +const QStringList& XGUI_Command::nestedCommands() const { - return myUnblockableCommands; + return myNestedCommands; } -void XGUI_Command::setUnblockableCommands(const QStringList& myUnblockableCommands) +void XGUI_Command::setNestedCommands(const QStringList& myUnblockableCommands) { - this->myUnblockableCommands = myUnblockableCommands; + this->myNestedCommands = myUnblockableCommands; } diff --git a/src/XGUI/XGUI_Command.h b/src/XGUI/XGUI_Command.h index dbd45b432..6c01e6136 100644 --- a/src/XGUI/XGUI_Command.h +++ b/src/XGUI/XGUI_Command.h @@ -25,8 +25,8 @@ public: return data().toString(); }*/ - const QStringList& unblockableCommands() const; - void setUnblockableCommands(const QStringList& myUnblockableCommands); + const QStringList& nestedCommands() const; + void setNestedCommands(const QStringList& myUnblockableCommands); //! Connect the command to a slot virtual void connectTo(const QObject* theResiver, const char* theSlot); @@ -38,7 +38,7 @@ protected: private: bool myCheckable; //! List of Ids of commands which WILL NOT be blocked when the command is on. - QStringList myUnblockableCommands; + QStringList myNestedCommands; }; #endif diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index ad312dad5..2a27188c9 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -57,6 +57,15 @@ bool XGUI_OperationMgr::abortOperation() return true; } +QStringList XGUI_OperationMgr::operationList() +{ + QStringList result; + foreach(ModuleBase_Operation* eachOperation, myOperations) { + result << eachOperation->id(); + } + return result; +} + void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation) { theOperation->resume(); @@ -106,11 +115,11 @@ void XGUI_OperationMgr::onOperationStopped() if (!aSenderOperation || !anOperation || aSenderOperation != anOperation ) return; - emit operationStopped(anOperation); - myOperations.removeAll(anOperation); anOperation->deleteLater(); + emit operationStopped(anOperation); + // get last operation which can be resumed ModuleBase_Operation* aResultOp = 0; QListIterator anIt(myOperations); diff --git a/src/XGUI/XGUI_OperationMgr.h b/src/XGUI/XGUI_OperationMgr.h index 169453b3a..56db2c4c5 100644 --- a/src/XGUI/XGUI_OperationMgr.h +++ b/src/XGUI/XGUI_OperationMgr.h @@ -11,6 +11,7 @@ #include #include +#include /**\class XGUI_OperationMgr * \ingroup GUI @@ -46,6 +47,8 @@ public: /// Abort the operation and append it to the stack of operations /// \return the state whether the current operation is aborted bool abortOperation(); + ///Returns list of all operations IDs + QStringList operationList(); signals: /// Signal about an operation is started. It is emitted after the start() of operation is done. diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 9d064f210..0313eb3ba 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -92,10 +92,11 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) myViewerProxy = new XGUI_ViewerProxy(this); - connect(myOperationMgr, SIGNAL(operationStarted()), this, SLOT(onOperationStarted())); - connect(myOperationMgr, SIGNAL(operationResumed()), this, SLOT(onOperationStarted())); - connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), - this, SLOT(onOperationStopped(ModuleBase_Operation*))); + connect(myOperationMgr, SIGNAL(operationStarted()), SLOT(onOperationStarted())); + connect(myOperationMgr, SIGNAL(operationResumed()), SLOT(onOperationStarted())); + connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), SLOT(onOperationStopped(ModuleBase_Operation*))); + connect(myOperationMgr, SIGNAL(operationStarted()), myActionsMgr, SLOT(update())); + connect(myOperationMgr, SIGNAL(operationStopped()), myActionsMgr, SLOT(update())); connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&))); } @@ -188,6 +189,12 @@ void XGUI_Workshop::initMenu() aCommand = aGroup->addFeature("EXIT_CMD", tr("Exit"), tr("Exit application"), QIcon(":pictures/close.png"), QKeySequence::Close); aCommand->connectTo(this, SLOT(onExit())); + //FIXME: SBH's test action. Can be used for some GUI tests. + //#ifdef _DEBUG + // aCommand = aGroup->addFeature("TEST_CMD", "Test!", "Private debug button", + // QIcon(":pictures/close.png")); + // aCommand->connectTo(myActionsMgr, SLOT(update())); + //#endif } //****************************************************** @@ -288,18 +295,9 @@ void XGUI_Workshop::onOperationStarted() //****************************************************** void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) { - ModuleBase_Operation* aOperation = myOperationMgr->currentOperation(); - //!< No need for property panel updateCommandStatus(); hidePropertyPanel(); - if(myOperationMgr->operationsCount() > 1) { - myActionsMgr->updateAction(theOperation->getDescription()->operationId()); - return; - } - if(!aOperation->getDescription()->xmlRepresentation().isEmpty()) { - myActionsMgr->restoreCommandState(); - } } /* @@ -350,7 +348,7 @@ void XGUI_Workshop::addFeature(const Config_FeatureMessage* theMessage) QString::fromStdString(theMessage->tooltip()), QIcon(theMessage->icon().c_str()), QKeySequence(), isUsePropPanel); - aCommand->setUnblockableCommands(aNestedFeatures.split(" ")); + aCommand->setNestedCommands(aNestedFeatures.split(" ", QString::SkipEmptyParts)); myActionsMgr->addCommand(aCommand); myPartSetModule->featureCreated(aCommand); } @@ -591,6 +589,7 @@ bool XGUI_Workshop::activateModule() if (!myPartSetModule) return false; myPartSetModule->createFeatures(); + myActionsMgr->update(); return true; } @@ -632,6 +631,7 @@ void XGUI_Workshop::updateCommandStatus() aCmd->setEnabled(false); } } + myActionsMgr->update(); } //******************************************************