return result;\r
}\r
\r
+std::string getNormalizedProperty(xmlNodePtr theNode, const char* thePropName)\r
+{\r
+ return normalize(getProperty(theNode, thePropName));\r
+}\r
+\r
bool getBooleanAttribute(xmlNodePtr theNode, const char* theAttributeName, bool theDefault)\r
{\r
std::string prop = normalize(getProperty(theNode, theAttributeName));\r
*/
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
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;
+}
\r
bool myUseInput; ///<Action is being checked until user commit the operation\r
bool myInternal; ///<Internal feature without GUI representation\r
- std::string myNestedFeatures; ///<Comma separated list of child features\r
+ std::string myNestedFeatures; ///<Space separated list of child features\r
+ std::string myActionsWhenNested; ///<Space separated list of actions\r
\r
public:\r
/// Event ID that feature is loaded in workbench (GUI)\r
CONFIG_EXPORT const std::string& documentKind() const;\r
/// Name of a library which contains the feature\r
CONFIG_EXPORT const std::string& pluginLibrary() const;\r
- /// Comma separated list of nested features\r
+ /// Space separated list of nested features\r
CONFIG_EXPORT const std::string& nestedFeatures() const;\r
+ /// Space separated list of actions\r
+ CONFIG_EXPORT const std::string& actionsWhenNested() const;\r
/// If false - feature has no Property panel representation\r
CONFIG_EXPORT bool isUseInput() const;\r
/// If true - feature will not be added into the workbench\r
CONFIG_EXPORT void setDocumentKind(const std::string& documentKind);\r
///Set name of a library which contains the feature\r
CONFIG_EXPORT void setPluginLibrary(const std::string& thePluginLibrary);\r
- ///Set comma separated list of nested features\r
+ ///Set space separated list of nested features\r
CONFIG_EXPORT void setNestedFeatures(const std::string& theNestedFeatures);\r
+ ///Set space separated list of nested features\r
+ CONFIG_EXPORT void setActionsWhenNested(const std::string& theActions);\r
///Set use input state; If false - feature has no Property panel representation\r
CONFIG_EXPORT void setUseInput(bool isUseInput);\r
///Set internal state; If true - feature will not be added into the workbench\r
outFeatureMessage->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);
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";
<feature
id="Sketch"
nested="SketchPoint SketchLine SketchCircle SketchArc SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid"
+ when_nested="accept abort"
title="Sketch"
tooltip="Create a new sketch"
icon=":icons/sketch.png">
}
}
+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())
*/
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.
//! Redefinition of Events_Listener method
virtual void processEvent(const std::shared_ptr<Events_Message>& 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
void updateByPlugins(FeaturePtr theActiveFeature);
private:
+
QMap<QString, QAction*> myActions;
QMap<QString, QStringList> myNestedActions;
+ QMap<OperationStateActionId, QAction*> myOperationActions;
QList<QKeySequence> myShortcuts;
XGUI_Workshop* myWorkshop;
return result;
}
+bool XGUI_OperationMgr::commitAllOperations()
+{
+ while (hasOperation()) {
+ if (isApplyEnabled()) {
+ onCommitOperation();
+ } else {
+ currentOperation()->abort();
+ }
+ }
+ return true;
+}
+
void XGUI_OperationMgr::onValidateOperation()
{
if (!hasOperation())
void XGUI_OperationMgr::setApplyEnabled(const bool theEnabled)
{
myIsApplyEnabled = theEnabled;
- emit applyEnableChanged(theEnabled);
+ emit validationStateChanged(theEnabled);
}
bool XGUI_OperationMgr::isApplyEnabled() const
void XGUI_OperationMgr::onOperationStarted()
{
ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
+ if (myOperations.count() == 1) {
+ emit nestedStateChanged(false);
+ }
emit operationStarted(aSenderOperation);
}
void XGUI_OperationMgr::onOperationCommitted()
{
ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
+ emit nestedStateChanged(true);
emit operationCommitted(aSenderOperation);
}
/// \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
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.
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();
*/
#include <XGUI_PropertyPanel.h>
+#include <XGUI_ActionsMgr.h>
//#include <AppElements_Constants.h>
#include <ModuleBase_WidgetMultiSelector.h>
-#include <QWidget>
-#include <QVBoxLayout>
+#include <QEvent>
#include <QFrame>
-#include <QPushButton>
#include <QIcon>
-#include <QVBoxLayout>
-#include <QEvent>
#include <QKeyEvent>
#include <QLayoutItem>
+#include <QToolButton>
+#include <QVBoxLayout>
+#include <QVBoxLayout>
+#include <QWidget>
+#include <QToolButton>
+#include <QAction>
#ifdef _DEBUG
#include <iostream>
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);
if (!aControls.empty()) {
QWidget* aLastControl = aControls.last();
- QPushButton* anOkBtn = findChild<QPushButton*>(PROP_PANEL_OK);
- QPushButton* aCancelBtn = findChild<QPushButton*>(PROP_PANEL_CANCEL);
+ QToolButton* anOkBtn = findChild<QToolButton*>(PROP_PANEL_OK);
+ QToolButton* aCancelBtn = findChild<QToolButton*>(PROP_PANEL_CANCEL);
setTabOrder(aLastControl, anOkBtn);
setTabOrder(anOkBtn, aCancelBtn);
activateNextWidget(myActiveWidget);
}
-void XGUI_PropertyPanel::setAcceptEnabled(bool isEnabled)
-{
- QPushButton* anOkBtn = findChild<QPushButton*>(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
void XGUI_PropertyPanel::setCancelEnabled(bool theEnabled)
{
- QPushButton* anCancelBtn = findChild<QPushButton*>(PROP_PANEL_CANCEL);
+ QToolButton* anCancelBtn = findChild<QToolButton*>(PROP_PANEL_CANCEL);
anCancelBtn->setEnabled(theEnabled);
}
bool XGUI_PropertyPanel::isCancelEnabled() const
{
- QPushButton* anCancelBtn = findChild<QPushButton*>(PROP_PANEL_CANCEL);
+ QToolButton* anCancelBtn = findChild<QToolButton*>(PROP_PANEL_CANCEL);
return anCancelBtn->isEnabled();
}
aWgt->setEditingMode(isEditing);
}
}
+
+void XGUI_PropertyPanel::setupActions(XGUI_ActionsMgr* theMgr)
+{
+ QStringList aButtonNames;
+ aButtonNames << PROP_PANEL_OK << PROP_PANEL_CANCEL << PROP_PANEL_HELP;
+ QList<XGUI_ActionsMgr::OperationStateActionId> aActionIds;
+ aActionIds << XGUI_ActionsMgr::Accept << XGUI_ActionsMgr::Abort << XGUI_ActionsMgr::Help;
+ for (int i = 0; i < aButtonNames.size(); ++i) {
+ QToolButton* aBtn = findChild<QToolButton*>(aButtonNames.at(i));
+ QAction* anAct = theMgr->operationStateAction(aActionIds.at(i));
+ aBtn->setDefaultAction(anAct);
+ }
+}
#include <QList>
+class XGUI_ActionsMgr;
class QKeyEvent;
class QVBoxLayout;
/// 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.
/// \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
#include <AppElements_MainMenu.h>
#include <AppElements_MainWindow.h>
#include <AppElements_MenuGroupPanel.h>
+#include <AppElements_Button.h>
#include <ModuleBase_IModule.h>
#include <ModuleBase_Preferences.h>
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<QToolButton*>(aGroup->widget(aUndoId));
+ AppElements_Button* aUndoButton = qobject_cast<AppElements_Button*>(aGroup->widget(aUndoId));
addHistoryMenu(aUndoButton,
SIGNAL(updateUndoHistory(const QList<ActionInfo>&)),
SLOT(onUndo(int)));
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<QToolButton*>(aGroup->widget(aRedoId));
+ AppElements_Button* aRedoButton = qobject_cast<AppElements_Button*>(aGroup->widget(aRedoId));
addHistoryMenu(aRedoButton,
SIGNAL(updateRedoHistory(const QList<ActionInfo>&)),
SLOT(onRedo(int)));
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<QAction*> 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);
}
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(); ///<! Invisible by default
hideObjectBrowser();
aDesktop->tabifyDockWidget(aObjDock, myPropertyPanel);
myPropertyPanel->installEventFilter(myOperationMgr);
- QPushButton* aOkBtn = myPropertyPanel->findChild<QPushButton*>(PROP_PANEL_OK);
- connect(aOkBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onCommitOperation()));
- QPushButton* aCancelBtn = myPropertyPanel->findChild<QPushButton*>(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)));
}