From 6c11e01149120ed3cbdb92d39ceb34e49e6670ae Mon Sep 17 00:00:00 2001 From: sbh Date: Thu, 12 Feb 2015 17:35:05 +0300 Subject: [PATCH] Whole column button with accept/abort actions is implemented --- src/Config/Config_Common.cpp | 5 ++ src/Config/Config_Common.h | 5 ++ src/Config/Config_FeatureMessage.cpp | 10 ++++ src/Config/Config_FeatureMessage.h | 11 +++-- src/Config/Config_FeatureReader.cpp | 1 + src/Config/Config_Keywords.h | 1 + src/SketchPlugin/plugin-Sketch.xml | 1 + src/XGUI/XGUI_ActionsMgr.cpp | 29 ++++++++++++ src/XGUI/XGUI_ActionsMgr.h | 20 ++++++-- src/XGUI/XGUI_OperationMgr.cpp | 18 +++++++- src/XGUI/XGUI_OperationMgr.h | 12 +++-- src/XGUI/XGUI_PropertyPanel.cpp | 68 +++++++++++++++------------- src/XGUI/XGUI_PropertyPanel.h | 11 +++-- src/XGUI/XGUI_Workshop.cpp | 51 +++++++++++++++------ 14 files changed, 182 insertions(+), 61 deletions(-) diff --git a/src/Config/Config_Common.cpp b/src/Config/Config_Common.cpp index 2da152dcc..9c4df7f57 100644 --- a/src/Config/Config_Common.cpp +++ b/src/Config/Config_Common.cpp @@ -128,6 +128,11 @@ std::string getProperty(xmlNodePtr theNode, const char* thePropName) return result; } +std::string getNormalizedProperty(xmlNodePtr theNode, const char* thePropName) +{ + return normalize(getProperty(theNode, thePropName)); +} + bool getBooleanAttribute(xmlNodePtr theNode, const char* theAttributeName, bool theDefault) { std::string prop = normalize(getProperty(theNode, theAttributeName)); diff --git a/src/Config/Config_Common.h b/src/Config/Config_Common.h index e6d641d2e..c53586eb5 100644 --- a/src/Config/Config_Common.h +++ b/src/Config/Config_Common.h @@ -81,6 +81,11 @@ CONFIG_EXPORT std::string library(const std::string& theLibName); */ CONFIG_EXPORT std::string getProperty(xmlNodePtr theNode, const char* thePropName); +/*! + * Returns normalized (lower case) named property for a given node as std::string. + */ +std::string getNormalizedProperty(xmlNodePtr theNode, const char* thePropName); + /*! * Checks if the given XML node has the given attribute, * if yes - returns it's bool value, if no, or if the value can not diff --git a/src/Config/Config_FeatureMessage.cpp b/src/Config/Config_FeatureMessage.cpp index b925ab656..954099ea3 100644 --- a/src/Config/Config_FeatureMessage.cpp +++ b/src/Config/Config_FeatureMessage.cpp @@ -140,7 +140,17 @@ const std::string& Config_FeatureMessage::nestedFeatures() const return myNestedFeatures; } +const std::string& Config_FeatureMessage::actionsWhenNested() const +{ + return myActionsWhenNested; +} + void Config_FeatureMessage::setNestedFeatures(const std::string& theNestedFeatures) { myNestedFeatures = theNestedFeatures; } + +void Config_FeatureMessage::setActionsWhenNested(const std::string& theActions) +{ + myActionsWhenNested = theActions; +} diff --git a/src/Config/Config_FeatureMessage.h b/src/Config/Config_FeatureMessage.h index bfc63dd05..98201cf6f 100644 --- a/src/Config/Config_FeatureMessage.h +++ b/src/Config/Config_FeatureMessage.h @@ -32,7 +32,8 @@ class Config_FeatureMessage : public Events_Message bool myUseInput; ///setId(getProperty(theFeatureNode, _ID)); outFeatureMessage->setPluginLibrary(myLibraryName); outFeatureMessage->setNestedFeatures(getProperty(theFeatureNode, FEATURE_NESTED)); + outFeatureMessage->setActionsWhenNested(getNormalizedProperty(theFeatureNode, FEATURE_WHEN_NESTED)); bool isInternal = getBooleanAttribute(theFeatureNode, ATTR_INTERNAL, false); outFeatureMessage->setInternal(isInternal); diff --git a/src/Config/Config_Keywords.h b/src/Config/Config_Keywords.h index a00d77080..afb80188b 100644 --- a/src/Config/Config_Keywords.h +++ b/src/Config/Config_Keywords.h @@ -49,6 +49,7 @@ const static char* FEATURE_ICON = "icon"; const static char* FEATURE_TEXT = "title"; const static char* FEATURE_KEYSEQUENCE = "keysequence"; const static char* FEATURE_NESTED = "nested"; +const static char* FEATURE_WHEN_NESTED = "when_nested"; const static char* FEATURE_DOC = WORKBENCH_DOC; // NODE_VALIDATOR properties, NODE_SELFILTER properties const static char* _PARAMETERS = "parameters"; diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 0f6201227..5018b9fd3 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -6,6 +6,7 @@ diff --git a/src/XGUI/XGUI_ActionsMgr.cpp b/src/XGUI/XGUI_ActionsMgr.cpp index 0d9c4d01f..c3613d22b 100644 --- a/src/XGUI/XGUI_ActionsMgr.cpp +++ b/src/XGUI/XGUI_ActionsMgr.cpp @@ -213,6 +213,35 @@ void XGUI_ActionsMgr::processEvent(const std::shared_ptr& theMes } } +QAction* XGUI_ActionsMgr::operationStateAction(OperationStateActionId theId, QObject* theParent) +{ + QAction* aResult = NULL; + if (myOperationActions.contains(theId)) { + aResult = myOperationActions.value(theId); + if (theParent && aResult->parent() != theParent) { + aResult->setParent(theParent); + } + } else { + switch (theId) { + case Accept: + case AcceptAll: + aResult = new QAction(QIcon(":pictures/button_ok.png"), "", theParent); + break; + case Abort: + case AbortAll: + aResult = new QAction(QIcon(":pictures/button_cancel.png"), "", theParent); + break; + case Help: + aResult = new QAction(QIcon(":pictures/button_help.png"), "", theParent); + break; + default: + break; + } + myOperationActions.insert(theId, aResult); + } + return aResult; +} + void XGUI_ActionsMgr::setAllEnabled(bool isEnabled) { foreach(QString eachAction, myActions.keys()) diff --git a/src/XGUI/XGUI_ActionsMgr.h b/src/XGUI/XGUI_ActionsMgr.h index 5c74e2b79..cbff72d12 100644 --- a/src/XGUI/XGUI_ActionsMgr.h +++ b/src/XGUI/XGUI_ActionsMgr.h @@ -29,14 +29,22 @@ class QAction; */ class XGUI_EXPORT XGUI_ActionsMgr : public QObject, public Events_Listener { -Q_OBJECT + Q_OBJECT public: - /// Constructor - /// \param theWorkshop an instance of workshop + /// Constructor + /// \param theWorkshop an instance of workshop XGUI_ActionsMgr(XGUI_Workshop* theWorkshop); virtual ~XGUI_ActionsMgr(); + enum OperationStateActionId { + Abort = 0, + Accept = 1, + Help = 2, + AbortAll = 3, + AcceptAll = 4 + }; + //! Add a command in the manager. //! Please note that nested commands in the Salome mode (No AppElements_Command, pure QActions) //! won't be extracted and should be added manually using the addNestedCommands method. @@ -65,6 +73,10 @@ Q_OBJECT //! Redefinition of Events_Listener method virtual void processEvent(const std::shared_ptr& theMessage); + //! Return property panel's action like ok, cancel, help. + //! If there is no such action, it will be created. + QAction* operationStateAction(OperationStateActionId theId, QObject* theParent = 0); + public slots: //! Update workbench actions according to OperationMgr state: //! No active operations: all actions but nested are available @@ -94,8 +106,10 @@ Q_OBJECT void updateByPlugins(FeaturePtr theActiveFeature); private: + QMap myActions; QMap myNestedActions; + QMap myOperationActions; QList myShortcuts; XGUI_Workshop* myWorkshop; diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index fa74ed503..007019a64 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -134,6 +134,18 @@ bool XGUI_OperationMgr::abortAllOperations() return result; } +bool XGUI_OperationMgr::commitAllOperations() +{ + while (hasOperation()) { + if (isApplyEnabled()) { + onCommitOperation(); + } else { + currentOperation()->abort(); + } + } + return true; +} + void XGUI_OperationMgr::onValidateOperation() { if (!hasOperation()) @@ -147,7 +159,7 @@ void XGUI_OperationMgr::onValidateOperation() void XGUI_OperationMgr::setApplyEnabled(const bool theEnabled) { myIsApplyEnabled = theEnabled; - emit applyEnableChanged(theEnabled); + emit validationStateChanged(theEnabled); } bool XGUI_OperationMgr::isApplyEnabled() const @@ -223,6 +235,9 @@ void XGUI_OperationMgr::onAbortOperation() void XGUI_OperationMgr::onOperationStarted() { ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + if (myOperations.count() == 1) { + emit nestedStateChanged(false); + } emit operationStarted(aSenderOperation); } @@ -235,6 +250,7 @@ void XGUI_OperationMgr::onOperationAborted() void XGUI_OperationMgr::onOperationCommitted() { ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + emit nestedStateChanged(true); emit operationCommitted(aSenderOperation); } diff --git a/src/XGUI/XGUI_OperationMgr.h b/src/XGUI/XGUI_OperationMgr.h index e69eb70fa..525123137 100644 --- a/src/XGUI/XGUI_OperationMgr.h +++ b/src/XGUI/XGUI_OperationMgr.h @@ -74,9 +74,6 @@ Q_OBJECT /// \return the state whether the current operation is started bool startOperation(ModuleBase_Operation* theOperation); - /// Abort all operations - bool abortAllOperations(); - /// Returns whether the operation can be started. Check if there is already started operation and /// the granted parameter of the launched operation /// \param theId id of the operation which is going to start @@ -104,6 +101,10 @@ Q_OBJECT void onAbortOperation(); /// Slot that validates the current operation using the validateOperation method. void onValidateOperation(); + /// Commit all operations + bool commitAllOperations(); + /// Abort all operations + bool abortAllOperations(); signals: /// Signal about an operation is started. It is emitted after the start() of operation is done. @@ -123,7 +124,10 @@ signals: void operationAborted(ModuleBase_Operation* theOperation); /// Signal is emitted after the apply enable state changed. - void applyEnableChanged(bool); + void validationStateChanged(bool); + + /// Signal is emitted after the apply enable state changed. + void nestedStateChanged(bool); /// Signal is emitted after the current operation is filled with existing preselection. void operationActivatedByPreselection(); diff --git a/src/XGUI/XGUI_PropertyPanel.cpp b/src/XGUI/XGUI_PropertyPanel.cpp index 22c56c2a3..355614b76 100644 --- a/src/XGUI/XGUI_PropertyPanel.cpp +++ b/src/XGUI/XGUI_PropertyPanel.cpp @@ -8,18 +8,21 @@ */ #include +#include //#include #include -#include -#include +#include #include -#include #include -#include -#include #include #include +#include +#include +#include +#include +#include +#include #ifdef _DEBUG #include @@ -46,22 +49,18 @@ XGUI_PropertyPanel::XGUI_PropertyPanel(QWidget* theParent) aBtnLay->setContentsMargins(0, 0, 0, 0); myMainLayout->addWidget(aFrm); - QPushButton* aBtn = new QPushButton(QIcon(":pictures/button_help.png"), "", aFrm); - aBtn->setFlat(true); - aBtnLay->addWidget(aBtn); - aBtnLay->addStretch(1); - aBtn = new QPushButton(QIcon(":pictures/button_ok.png"), "", aFrm); - aBtn->setObjectName(PROP_PANEL_OK); - aBtn->setToolTip(tr("Ok")); - aBtn->setFlat(true); - aBtnLay->addWidget(aBtn); - - aBtn = new QPushButton(QIcon(":pictures/button_cancel.png"), "", aFrm); - aBtn->setToolTip(tr("Cancel")); - aBtn->setObjectName(PROP_PANEL_CANCEL); - aBtn->setFlat(true); - aBtn->setShortcut(QKeySequence(Qt::Key_Escape)); - aBtnLay->addWidget(aBtn); + QStringList aBtnNames; + aBtnNames << QString(PROP_PANEL_HELP) + << QString(PROP_PANEL_OK) + << QString(PROP_PANEL_CANCEL); + foreach(QString eachBtnName, aBtnNames) { + QToolButton* aBtn = new QToolButton(aFrm); + aBtn->setObjectName(eachBtnName); + aBtn->setAutoRaise(true); + aBtnLay->addWidget(aBtn); + } + aBtnLay->insertStretch(1, 1); + // aBtn->setShortcut(QKeySequence(Qt::Key_Escape)); myCustomWidget = new QWidget(aContent); myMainLayout->addWidget(myCustomWidget); @@ -118,8 +117,8 @@ void XGUI_PropertyPanel::setModelWidgets(const QList& t if (!aControls.empty()) { QWidget* aLastControl = aControls.last(); - QPushButton* anOkBtn = findChild(PROP_PANEL_OK); - QPushButton* aCancelBtn = findChild(PROP_PANEL_CANCEL); + QToolButton* anOkBtn = findChild(PROP_PANEL_OK); + QToolButton* aCancelBtn = findChild(PROP_PANEL_CANCEL); setTabOrder(aLastControl, anOkBtn); setTabOrder(anOkBtn, aCancelBtn); @@ -198,12 +197,6 @@ void XGUI_PropertyPanel::activateNextWidget() activateNextWidget(myActiveWidget); } -void XGUI_PropertyPanel::setAcceptEnabled(bool isEnabled) -{ - QPushButton* anOkBtn = findChild(PROP_PANEL_OK); - anOkBtn->setEnabled(isEnabled); -} - void XGUI_PropertyPanel::activateWidget(ModuleBase_ModelWidget* theWidget) { // Avoid activation of already actve widget. It could happen on focusIn event many times @@ -228,13 +221,13 @@ void XGUI_PropertyPanel::activateWidget(ModuleBase_ModelWidget* theWidget) void XGUI_PropertyPanel::setCancelEnabled(bool theEnabled) { - QPushButton* anCancelBtn = findChild(PROP_PANEL_CANCEL); + QToolButton* anCancelBtn = findChild(PROP_PANEL_CANCEL); anCancelBtn->setEnabled(theEnabled); } bool XGUI_PropertyPanel::isCancelEnabled() const { - QPushButton* anCancelBtn = findChild(PROP_PANEL_CANCEL); + QToolButton* anCancelBtn = findChild(PROP_PANEL_CANCEL); return anCancelBtn->isEnabled(); } @@ -245,3 +238,16 @@ void XGUI_PropertyPanel::setEditingMode(bool isEditing) aWgt->setEditingMode(isEditing); } } + +void XGUI_PropertyPanel::setupActions(XGUI_ActionsMgr* theMgr) +{ + QStringList aButtonNames; + aButtonNames << PROP_PANEL_OK << PROP_PANEL_CANCEL << PROP_PANEL_HELP; + QList aActionIds; + aActionIds << XGUI_ActionsMgr::Accept << XGUI_ActionsMgr::Abort << XGUI_ActionsMgr::Help; + for (int i = 0; i < aButtonNames.size(); ++i) { + QToolButton* aBtn = findChild(aButtonNames.at(i)); + QAction* anAct = theMgr->operationStateAction(aActionIds.at(i)); + aBtn->setDefaultAction(anAct); + } +} diff --git a/src/XGUI/XGUI_PropertyPanel.h b/src/XGUI/XGUI_PropertyPanel.h index c202af395..c70e0aec7 100644 --- a/src/XGUI/XGUI_PropertyPanel.h +++ b/src/XGUI/XGUI_PropertyPanel.h @@ -17,6 +17,7 @@ #include +class XGUI_ActionsMgr; class QKeyEvent; class QVBoxLayout; @@ -29,6 +30,9 @@ const static char* PROP_PANEL_OK = "property_panel_ok"; /// Internal name of Cancel button const static char* PROP_PANEL_CANCEL = "property_panel_cancel"; +/// Internal name of Help button +const static char* PROP_PANEL_HELP = "property_panel_help"; + /** * \ingroup GUI * Realization of Property panel object. @@ -82,16 +86,15 @@ Q_OBJECT /// \param isEditing state of editing mode flag virtual void setEditingMode(bool isEditing); + //! Allows to set predefined actions for the property panel fetched from the ActionsMgr + void setupActions(XGUI_ActionsMgr* theMgr); + public slots: /// \brief Update all widgets in property panel with values from the given feature /// \param theFeature a Feature to update values in widgets void updateContentWidget(FeaturePtr theFeature); - /// Enables / disables "ok" ("accept") button - /// \param toEnable enable/disable state of button - void setAcceptEnabled(bool toEnable); - /** * Makes the given widget active, highlights it and removes * highlighting from the previous active widget diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 84d3d6a10..07624e29a 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -268,7 +269,7 @@ void XGUI_Workshop::initMenu() aCommand = aGroup->addFeature(aUndoId, tr("Undo"), tr("Undo last command"), QIcon(":pictures/undo.png"), QKeySequence::Undo); aCommand->connectTo(this, SLOT(onUndo())); - QToolButton* aUndoButton = qobject_cast(aGroup->widget(aUndoId)); + AppElements_Button* aUndoButton = qobject_cast(aGroup->widget(aUndoId)); addHistoryMenu(aUndoButton, SIGNAL(updateUndoHistory(const QList&)), SLOT(onUndo(int))); @@ -277,7 +278,7 @@ void XGUI_Workshop::initMenu() aCommand = aGroup->addFeature(aRedoId, tr("Redo"), tr("Redo last command"), QIcon(":pictures/redo.png"), QKeySequence::Redo); aCommand->connectTo(this, SLOT(onRedo())); - QToolButton* aRedoButton = qobject_cast(aGroup->widget(aRedoId)); + AppElements_Button* aRedoButton = qobject_cast(aGroup->widget(aRedoId)); addHistoryMenu(aRedoButton, SIGNAL(updateRedoHistory(const QList&)), SLOT(onRedo(int))); @@ -725,8 +726,26 @@ void XGUI_Workshop::addFeature(const std::shared_ptr& the aFeatureInfo.shortcut = aHotKey; } // Create feature... - AppElements_Command* aCommand = aGroup->addFeature(aFeatureInfo, aDocKind); - aCommand->setNestedCommands(aNestedFeatures); + AppElements_Command* aCommand = aGroup->addFeature(aFeatureInfo, + aDocKind, + aNestedFeatures); + // Enrich created button with accept/abort buttons if necessary + AppElements_Button* aButton = aCommand->button(); + if (aButton->isColumnButton()) { + QString aNestedActions = QString::fromStdString(theMessage->actionsWhenNested()); + QList anActList; + if (aNestedActions.contains("accept")) { + QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, aButton); + connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(commitAllOperations())); + anActList << anAction; + } + if (aNestedActions.contains("abort")) { + QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll, aButton); + connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(abortAllOperations())); + anActList << anAction; + } + aButton->setAdditionalButtons(anActList); + } myActionsMgr->addCommand(aCommand); myModule->actionCreated(aCommand); } @@ -1136,24 +1155,26 @@ void XGUI_Workshop::createDockWidgets() QDockWidget* aObjDock = createObjectBrowser(aDesktop); aDesktop->addDockWidget(Qt::LeftDockWidgetArea, aObjDock); myPropertyPanel = new XGUI_PropertyPanel(aDesktop); + myPropertyPanel->setupActions(myActionsMgr); myPropertyPanel->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); - - connect(myPropertyPanel, SIGNAL(noMoreWidgets()), myModule, SLOT(onNoMoreWidgets())); - aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel); hidePropertyPanel(); ///tabifyDockWidget(aObjDock, myPropertyPanel); myPropertyPanel->installEventFilter(myOperationMgr); - QPushButton* aOkBtn = myPropertyPanel->findChild(PROP_PANEL_OK); - connect(aOkBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onCommitOperation())); - QPushButton* aCancelBtn = myPropertyPanel->findChild(PROP_PANEL_CANCEL); - connect(aCancelBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onAbortOperation())); - connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)), myOperationMgr, - SLOT(onKeyReleased(QKeyEvent*))); - connect(myOperationMgr, SIGNAL(applyEnableChanged(bool)), myPropertyPanel, - SLOT(setAcceptEnabled(bool))); + QAction* aOkAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept); + connect(aOkAct, SIGNAL(triggered()), myOperationMgr, SLOT(onCommitOperation())); + QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort); + connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation())); + connect(myPropertyPanel, SIGNAL(noMoreWidgets()), myModule, SLOT(onNoMoreWidgets())); + connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)), + myOperationMgr, SLOT(onKeyReleased(QKeyEvent*))); + connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), + aOkAct, SLOT(setEnabled(bool))); + QAction* aAcceptAllAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll); + connect(myOperationMgr, SIGNAL(nestedStateChanged(bool)), + aAcceptAllAct, SLOT(setEnabled(bool))); } -- 2.39.2