From 73b63afd03a150740406d8c5cebf45ac5125f2e3 Mon Sep 17 00:00:00 2001 From: nds Date: Wed, 9 Sep 2015 14:09:33 +0300 Subject: [PATCH] Issue #905 Update of invalid feature representation in property panel --- src/ModuleBase/ModuleBase_IErrorMgr.h | 2 +- src/PartSet/PartSet_WidgetSketchLabel.cpp | 1 + src/XGUI/XGUI_ErrorMgr.cpp | 97 ++++++++++++++++++---- src/XGUI/XGUI_ErrorMgr.h | 30 ++++++- src/XGUI/XGUI_Workshop.cpp | 38 ++++++++- src/XGUI/XGUI_Workshop.h | 19 +++++ src/XGUI/XGUI_WorkshopListener.cpp | 9 +- src/XGUI/XGUI_pictures.qrc | 1 + src/XGUI/pictures/button_ok_error.png | Bin 0 -> 549 bytes 9 files changed, 175 insertions(+), 22 deletions(-) create mode 100755 src/XGUI/pictures/button_ok_error.png diff --git a/src/ModuleBase/ModuleBase_IErrorMgr.h b/src/ModuleBase/ModuleBase_IErrorMgr.h index c45918333..d64237253 100644 --- a/src/ModuleBase/ModuleBase_IErrorMgr.h +++ b/src/ModuleBase/ModuleBase_IErrorMgr.h @@ -30,7 +30,7 @@ public: public slots: /// SLOT, that is called after the operation is validated and feature validation errors have changed. - virtual void onValidationStateChanged() = 0; + //virtual void onValidationStateChanged() = 0; protected slots: /// Process values changed event for processing feature attribute validation errors. diff --git a/src/PartSet/PartSet_WidgetSketchLabel.cpp b/src/PartSet/PartSet_WidgetSketchLabel.cpp index 57cca495a..12d720a3c 100644 --- a/src/PartSet/PartSet_WidgetSketchLabel.cpp +++ b/src/PartSet/PartSet_WidgetSketchLabel.cpp @@ -182,6 +182,7 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs //XGUI_Displayer* aDisp = workshop()->displayer(); //aDisp->closeLocalContexts(); emit planeSelected(plane()); + emit valuesChanged(); // after the plane is selected in the sketch, the sketch selection should be activated // it can not be performed in the sketch label widget because, we don't need to switch off // the selection by any label deactivation, but need to switch it off by stop the sketch diff --git a/src/XGUI/XGUI_ErrorMgr.cpp b/src/XGUI/XGUI_ErrorMgr.cpp index cd4c50aa6..8f380127f 100644 --- a/src/XGUI/XGUI_ErrorMgr.cpp +++ b/src/XGUI/XGUI_ErrorMgr.cpp @@ -17,9 +17,21 @@ #include #include +#include +#include +#include +#include +#include +#include +#include + +const QString INVALID_VALUE = "invalid_action"; + XGUI_ErrorMgr::XGUI_ErrorMgr(QObject* theParent /*= 0*/) - : ModuleBase_IErrorMgr(theParent) + : ModuleBase_IErrorMgr(theParent), + myErrorDialog(0), + myErrorLabel(0) { } @@ -29,6 +41,55 @@ XGUI_ErrorMgr::~XGUI_ErrorMgr() } +bool XGUI_ErrorMgr::canProcessClick(QAction* theAction, const FeaturePtr& theFeature) +{ + QString aData = theAction->data().toString(); + + bool isActionEnabled = theAction->data() != INVALID_VALUE; + + QString anError = getFeatureError(theFeature); + if (!isActionEnabled && !anError.isEmpty()) { + if (!myErrorDialog) { + myErrorDialog = new QDialog(QApplication::desktop(), Qt::Popup); + QHBoxLayout* aLay = new QHBoxLayout(myErrorDialog); + aLay->setContentsMargins(0, 0, 0, 0); + + QFrame* aMarginWidget = new QFrame(myErrorDialog); + aMarginWidget->setFrameStyle(QFrame::Panel | QFrame::Raised); + + aLay->addWidget(aMarginWidget); + QHBoxLayout* aMarginLay = new QHBoxLayout(aMarginWidget); + aMarginLay->setContentsMargins(4, 4, 4, 4); + + myErrorLabel = new QLabel(aMarginWidget); + aMarginLay->addWidget(myErrorLabel); + } + myErrorLabel->setText(anError); + myErrorDialog->move(QCursor::pos()); + myErrorDialog->show(); + } + return isActionEnabled; +} + +void XGUI_ErrorMgr::updateActionState(QAction* theAction, const FeaturePtr& theFeature, + const bool theEnabled) +{ + bool isActionEnabled = theAction->data() != INVALID_VALUE; + if (theEnabled == isActionEnabled) + return; + + theAction->setIcon(theEnabled ? QIcon(":pictures/button_ok.png"): QIcon(":pictures/button_ok_error.png")); + QWidget* aWidget = myPropertyPanel->headerWidget(); + if (theEnabled) { + theAction->setData(""); + aWidget->setToolTip(""); + } + else { + theAction->setData(INVALID_VALUE); + aWidget->setToolTip(getFeatureError(theFeature)); + } +} + const char* toString(ModelAPI_ExecState theExecState) { #define TO_STRING(__NAME__) case __NAME__: return #__NAME__; @@ -43,7 +104,7 @@ const char* toString(ModelAPI_ExecState theExecState) #undef TO_STRING } -void XGUI_ErrorMgr::onValidationStateChanged() +/*void XGUI_ErrorMgr::onValidationStateChanged() { XGUI_OperationMgr* anOperationMgr = dynamic_cast(sender()); if (!anOperationMgr) @@ -53,25 +114,33 @@ void XGUI_ErrorMgr::onValidationStateChanged() if (!myPropertyPanel || !aFOperation) return; - // get feature FeaturePtr aFeature = aFOperation->feature(); - if (!aFeature.get() || !aFeature->data()->isValid()) - return; - - // set error indication - QString anError = QString::fromStdString(aFeature->error()); - if (anError.isEmpty()) { - bool isDone = ( aFeature->data()->execState() == ModelAPI_StateDone - || aFeature->data()->execState() == ModelAPI_StateMustBeUpdated ); - if (!isDone) - anError = toString(aFeature->data()->execState()); - } + QString anError = getFeatureError(aFeature); QWidget* aWidget = myPropertyPanel->headerWidget(); if (aWidget) { aWidget->setToolTip(anError); aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;"); } +}*/ + +QString XGUI_ErrorMgr::getFeatureError(const FeaturePtr& theFeature) const +{ + QString anError; + // get feature + if (!theFeature.get() || !theFeature->data()->isValid()) + return anError; + + // set error indication + anError = QString::fromStdString(theFeature->error()); + if (anError.isEmpty()) { + bool isDone = ( theFeature->data()->execState() == ModelAPI_StateDone + || theFeature->data()->execState() == ModelAPI_StateMustBeUpdated ); + if (!isDone) + anError = toString(theFeature->data()->execState()); + } + + return anError; } void XGUI_ErrorMgr::onWidgetChanged() diff --git a/src/XGUI/XGUI_ErrorMgr.h b/src/XGUI/XGUI_ErrorMgr.h index 36644798c..b370da0b7 100644 --- a/src/XGUI/XGUI_ErrorMgr.h +++ b/src/XGUI/XGUI_ErrorMgr.h @@ -10,6 +10,11 @@ #include "XGUI.h" #include +#include + +class QAction; +class QDialog; +class QLabel; class XGUI_EXPORT XGUI_ErrorMgr : public ModuleBase_IErrorMgr { @@ -19,13 +24,36 @@ public: /// Virtual destructor virtual ~XGUI_ErrorMgr(); + /// It updates the action state according to the given parameter + /// \param theAction an action to be changed + /// \param theFeature an feature that corresponds to the action + /// \param theEnabled an enable state + void updateActionState(QAction* theAction, const FeaturePtr& theFeature, + const bool theEnabled); + + /// Return true if the feature has no error. If there is an error and the action + /// is not valid, the dialog with the error information is shown. + /// \param theAction an action, which is checked on validity + /// \param theFeature a feature that provides error information + bool canProcessClick(QAction* theAction, const FeaturePtr& theFeature); + public slots: /// Reimplemented from ModuleBase_ErrorMgr::onValidationStateChanged(). - virtual void onValidationStateChanged(); + //virtual void onValidationStateChanged(); protected slots: /// Reimplemented from ModuleBase_ErrorMgr::onWidgetChanged(). virtual void onWidgetChanged(); + +private: + /// Returns the feature error message + /// \param theFeature a feature + /// \return the error message + QString getFeatureError(const FeaturePtr& theFeature) const; + +private: + QDialog* myErrorDialog; /// contains the error message + QLabel* myErrorLabel; /// contains an error information }; #endif // XGUI_ErrorMgr_H \ No newline at end of file diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index ebe199c4b..abe349cf2 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -157,8 +157,8 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) SLOT(onOperationCommitted(ModuleBase_Operation*))); connect(myOperationMgr, SIGNAL(operationAborted(ModuleBase_Operation*)), SLOT(onOperationAborted(ModuleBase_Operation*))); - connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), - myErrorMgr, SLOT(onValidationStateChanged())); + //connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), + // myErrorMgr, SLOT(onValidationStateChanged())); if (myMainWindow) connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit())); @@ -376,6 +376,35 @@ void XGUI_Workshop::onStartWaiting() } } +//****************************************************** +void XGUI_Workshop::onAcceptActionClicked() +{ + QAction* anAction = dynamic_cast(sender()); + XGUI_OperationMgr* anOperationMgr = operationMgr(); + if (anOperationMgr) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperationMgr->currentOperation()); + if (aFOperation) { + if (errorMgr()->canProcessClick(anAction, aFOperation->feature())) + myOperationMgr->onCommitOperation(); + } + } +} + +//****************************************************** +void XGUI_Workshop::onValidationStateChanged(bool theEnabled) +{ + XGUI_OperationMgr* anOperationMgr = operationMgr(); + if (anOperationMgr) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperationMgr->currentOperation()); + if (aFOperation) { + QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept); + myErrorMgr->updateActionState(anAction, aFOperation->feature(), theEnabled); + } + } +} + //****************************************************** void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer) @@ -941,14 +970,15 @@ void XGUI_Workshop::createDockWidgets() myPropertyPanel->installEventFilter(myOperationMgr); QAction* aOkAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept); - connect(aOkAct, SIGNAL(triggered()), myOperationMgr, SLOT(onCommitOperation())); + connect(aOkAct, SIGNAL(triggered()), this, SLOT(onAcceptActionClicked())); + 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))); + this, SLOT(onValidationStateChanged(bool))); } //****************************************************** diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index 351149422..4c8b51c1f 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -92,6 +92,12 @@ Q_OBJECT return myOperationMgr; } + //! ! Returns error manager. + XGUI_ErrorMgr* errorMgr() const + { + return myErrorMgr; + } + //! ! Returns an actions manager XGUI_ActionsMgr* actionsMgr() const { @@ -357,6 +363,19 @@ private: /// Set waiting cursor void onStartWaiting(); + /// Called by Ok button clicked in the property panel. Asks the error manager whether + /// the operation can be commited and do it if it returns true. + void onAcceptActionClicked(); + + /// Listens the corresponded signal from operation manager and send it with the Ok + /// action to operation manager. + /// \param theEnabled an enabled state for the action + void onValidationStateChanged(bool theEnabled); + + //connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), + // aOkAct, SLOT(setEnabled(bool))); + + private: /// Init menu void initMenu(); diff --git a/src/XGUI/XGUI_WorkshopListener.cpp b/src/XGUI/XGUI_WorkshopListener.cpp index 82620e635..ef3c66d55 100755 --- a/src/XGUI/XGUI_WorkshopListener.cpp +++ b/src/XGUI/XGUI_WorkshopListener.cpp @@ -3,6 +3,7 @@ #include "XGUI_WorkshopListener.h" #include "XGUI_Workshop.h" #include "XGUI_Displayer.h" +#include "XGUI_ErrorMgr.h" #include "XGUI_OperationMgr.h" #include "XGUI_SalomeConnector.h" #include "XGUI_ActionsMgr.h" @@ -394,16 +395,20 @@ void XGUI_WorkshopListener::onNestedStateChanged(const std::string& theFeatureId //one button is used for all features, which can have nested actions, so it is obtained from // the action manager QAction* anAcceptAllAction = aWorkshop->actionsMgr()->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL); + bool aActionToBeUpdated = false; if (aWorkshop->isSalomeMode()) { XGUI_SalomeConnector* aSalomeConnector = aWorkshop->salomeConnector(); XGUI_ActionsMgr* anActionsMgr = aWorkshop->actionsMgr(); if (aSalomeConnector->isNestedFeature(anActionsMgr->action(theFeatureId.c_str()))) - anAcceptAllAction->setEnabled(theState); + aActionToBeUpdated = true; } else { AppElements_MainMenu* aMenuBar = aWorkshop->mainWindow()->menuObject(); AppElements_Command* aCommand = aMenuBar->feature(theFeatureId.c_str()); if (aCommand && aCommand->button()->additionalButtonWidget()) - anAcceptAllAction->setEnabled(theState); + aActionToBeUpdated = true; + } + if (aActionToBeUpdated) { + anAcceptAllAction->setEnabled(theState); } } diff --git a/src/XGUI/XGUI_pictures.qrc b/src/XGUI/XGUI_pictures.qrc index 1f53d9536..cda15df93 100644 --- a/src/XGUI/XGUI_pictures.qrc +++ b/src/XGUI/XGUI_pictures.qrc @@ -30,6 +30,7 @@ pictures/button_cancel.png pictures/button_help.png pictures/button_ok.png + pictures/button_ok_error.png pictures/assembly.png pictures/delete.png diff --git a/src/XGUI/pictures/button_ok_error.png b/src/XGUI/pictures/button_ok_error.png new file mode 100755 index 0000000000000000000000000000000000000000..bdb6191e71c2553886a13fca9456b9e7051433f0 GIT binary patch literal 549 zcmV+=0^0qFP)pF8gxZibW?9;ba!ELWdKlNX>N2bPDNB8 zb~7$DE-^4L^m3s900E&%L_t(IPof7xb3*1R%J6*G{YA-m>gk+&?)SduJ?Gr3XX#%k3_>9a z5+NNDAlxMge8I=<-If|FEx_4d4C>3I-4O!hOD8`zpjl~u2f}S=k{)@kFmZga6!Db- zEeG}L7{XI%2j&_qm9nMVRB0KL=p>%s8zAzdYs#f&9nm#(y^7l{m6NPOIvipW@qCOF z;x!;y3aby>YKN}47jWzeaK(-RC)qj2i$!2OOBx@xQ=BI4j52o)moNyV^kD4w!GPlA zTIueBf=TI#*n3sd&4w#H0}oI)&bvT6aDNke8!P$7NqtKcS4_TNSm3I(8~*l`iAme2mS@pw4KF1*ga1{xpa&m z+eF;fr--l0p-^gRL$v0KE2S&uO8DBGRX-COc8y*_tEH_0#EsH@kyKaA{I>?I^acjq nHPQp)R^sbN2Je5(-y^*MyT+~L?G1jY00000NkvXXu0mjf@>b%` literal 0 HcmV?d00001 -- 2.39.2