From eecc1410339bbfe9a7ba175a7555c4030bb4a80a Mon Sep 17 00:00:00 2001 From: spo Date: Wed, 22 Jul 2015 14:10:54 +0300 Subject: [PATCH] Error management -- Introduce ErrorMgr --- src/ModuleBase/CMakeLists.txt | 2 + src/ModuleBase/ModuleBase_IErrorMgr.cpp | 34 ++++++ src/ModuleBase/ModuleBase_IErrorMgr.h | 44 ++++++++ src/ModuleBase/ModuleBase_IPropertyPanel.h | 3 + src/XGUI/CMakeLists.txt | 2 + src/XGUI/XGUI_ErrorMgr.cpp | 114 +++++++++++++++++++++ src/XGUI/XGUI_ErrorMgr.h | 31 ++++++ src/XGUI/XGUI_PropertyPanel.cpp | 2 + src/XGUI/XGUI_PropertyPanel.h | 6 ++ src/XGUI/XGUI_Workshop.cpp | 7 ++ src/XGUI/XGUI_Workshop.h | 2 + 11 files changed, 247 insertions(+) create mode 100644 src/ModuleBase/ModuleBase_IErrorMgr.cpp create mode 100644 src/ModuleBase/ModuleBase_IErrorMgr.h create mode 100644 src/XGUI/XGUI_ErrorMgr.cpp create mode 100644 src/XGUI/XGUI_ErrorMgr.h diff --git a/src/ModuleBase/CMakeLists.txt b/src/ModuleBase/CMakeLists.txt index 54fc7c1b1..5e76d8985 100644 --- a/src/ModuleBase/CMakeLists.txt +++ b/src/ModuleBase/CMakeLists.txt @@ -12,6 +12,7 @@ SET(PROJECT_HEADERS ModuleBase_FilterFactory.h ModuleBase_FilterValidated.h ModuleBase_IDocumentDataModel.h + ModuleBase_IErrorMgr.h ModuleBase_IModule.h ModuleBase_IPrefMgr.h ModuleBase_IPropertyPanel.h @@ -59,6 +60,7 @@ SET(PROJECT_SOURCES ModuleBase_FilterFactory.cpp ModuleBase_FilterValidated.cpp ModuleBase_IDocumentDataModel.cpp + ModuleBase_IErrorMgr.cpp ModuleBase_IModule.cpp ModuleBase_IPrefMgr.cpp ModuleBase_IPropertyPanel.cpp diff --git a/src/ModuleBase/ModuleBase_IErrorMgr.cpp b/src/ModuleBase/ModuleBase_IErrorMgr.cpp new file mode 100644 index 000000000..1d1c8a8d2 --- /dev/null +++ b/src/ModuleBase/ModuleBase_IErrorMgr.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_ErrorMgr.cpp +// Created: 22 July 2015 +// Author: Sergey POKHODENKO + +#include "ModuleBase_IErrorMgr.h" + +#include "ModuleBase_IPropertyPanel.h" +#include "ModuleBase_ModelWidget.h" + +ModuleBase_IErrorMgr::ModuleBase_IErrorMgr(QObject* theParent /*= 0*/) + : QObject(theParent) + , myPropertyPanel(NULL) +{ + +} + +ModuleBase_IErrorMgr::~ModuleBase_IErrorMgr() +{ + +} + +void ModuleBase_IErrorMgr::setPropertyPanel(ModuleBase_IPropertyPanel* theProp) +{ + myPropertyPanel = theProp; + + if (myPropertyPanel) { + foreach(const ModuleBase_ModelWidget* aWgt, myPropertyPanel->modelWidgets()) { + connect(aWgt, SIGNAL(afterValuesChanged()), this, SLOT(onWidgetChanged())); + connect(aWgt, SIGNAL(afterValuesRestored()), this, SLOT(onWidgetChanged())); + } + } +} diff --git a/src/ModuleBase/ModuleBase_IErrorMgr.h b/src/ModuleBase/ModuleBase_IErrorMgr.h new file mode 100644 index 000000000..c45918333 --- /dev/null +++ b/src/ModuleBase/ModuleBase_IErrorMgr.h @@ -0,0 +1,44 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_IErrorMgr.h +// Created: 22 July 2015 +// Author: Sergey POKHODENKO + +#ifndef ModuleBase_IErrorMgr_H +#define ModuleBase_IErrorMgr_H + +#include "ModuleBase.h" +#include + +class ModuleBase_IPropertyPanel; + +class MODULEBASE_EXPORT ModuleBase_IErrorMgr : public QObject +{ + Q_OBJECT +public: + /// Default constructor + ModuleBase_IErrorMgr(QObject* theParent = 0); + /// Virtual destructor + virtual ~ModuleBase_IErrorMgr(); + + /// \brief Set property pane to the operation + /// \param theProp a property panel instance + virtual void setPropertyPanel(ModuleBase_IPropertyPanel* theProp); + + /// \return Currently installed property panel + ModuleBase_IPropertyPanel* propertyPanel() const { return myPropertyPanel; } + +public slots: + /// SLOT, that is called after the operation is validated and feature validation errors have changed. + virtual void onValidationStateChanged() = 0; + +protected slots: + /// Process values changed event for processing feature attribute validation errors. + virtual void onWidgetChanged() = 0; + +protected: + /// Access to property panel + ModuleBase_IPropertyPanel* myPropertyPanel; +}; + +#endif // ModuleBase_IErrorMgr_H \ No newline at end of file diff --git a/src/ModuleBase/ModuleBase_IPropertyPanel.h b/src/ModuleBase/ModuleBase_IPropertyPanel.h index 12c96548e..516fdf3a6 100644 --- a/src/ModuleBase/ModuleBase_IPropertyPanel.h +++ b/src/ModuleBase/ModuleBase_IPropertyPanel.h @@ -29,6 +29,9 @@ public: /// \param theParent is a parent of the property panel ModuleBase_IPropertyPanel(QWidget* theParent); + /// Returns header widget + virtual QWidget* headerWidget() const = 0; + /// Returns currently active widget virtual ModuleBase_ModelWidget* activeWidget() const = 0; diff --git a/src/XGUI/CMakeLists.txt b/src/XGUI/CMakeLists.txt index 1cc72f76c..704b5ea05 100644 --- a/src/XGUI/CMakeLists.txt +++ b/src/XGUI/CMakeLists.txt @@ -12,6 +12,7 @@ SET(PROJECT_HEADERS XGUI_DataModel.h XGUI_Displayer.h XGUI_ErrorDialog.h + XGUI_ErrorMgr.h XGUI_HistoryMenu.h XGUI_ModuleConnector.h XGUI_ObjectsBrowser.h @@ -39,6 +40,7 @@ SET(PROJECT_SOURCES XGUI_DataModel.cpp XGUI_Displayer.cpp XGUI_ErrorDialog.cpp + XGUI_ErrorMgr.cpp XGUI_HistoryMenu.cpp XGUI_ModuleConnector.cpp XGUI_ObjectsBrowser.cpp diff --git a/src/XGUI/XGUI_ErrorMgr.cpp b/src/XGUI/XGUI_ErrorMgr.cpp new file mode 100644 index 000000000..f46a9291e --- /dev/null +++ b/src/XGUI/XGUI_ErrorMgr.cpp @@ -0,0 +1,114 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: XGUI_ErrorMgr.cpp +// Created: 22 July 2015 +// Author: Sergey POKHODENKO + +#include "XGUI_ErrorMgr.h" + +#include "XGUI_OperationMgr.h" + +#include +#include + +#include +#include +#include + +#include + +XGUI_ErrorMgr::XGUI_ErrorMgr(QObject* theParent /*= 0*/) + : ModuleBase_IErrorMgr(theParent) +{ + +} + +XGUI_ErrorMgr::~XGUI_ErrorMgr() +{ + +} + +const char* toString(ModelAPI_ExecState theExecState) +{ +#define TO_STRING(__NAME__) case __NAME__: return #__NAME__; + switch (theExecState) { + TO_STRING(ModelAPI_StateDone) + TO_STRING(ModelAPI_StateMustBeUpdated) + TO_STRING(ModelAPI_StateExecFailed) + TO_STRING(ModelAPI_StateInvalidArgument) + TO_STRING(ModelAPI_StateNothing) + default: "Unknown ExecState."; + } +#undef TO_STRING +} + +void XGUI_ErrorMgr::onValidationStateChanged() +{ + XGUI_OperationMgr* anOperationMgr = dynamic_cast(sender()); + if (!anOperationMgr || !anOperationMgr->currentOperation()) + return; + + if (!myPropertyPanel) + return; + + // get feature + FeaturePtr aFeature = anOperationMgr->currentOperation()->feature(); + if (!aFeature.get()) + 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()); + } + + QWidget* aWidget = myPropertyPanel->headerWidget(); + if (aWidget) { + aWidget->setToolTip(anError); + aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;"); + } +} + +void XGUI_ErrorMgr::onWidgetChanged() +{ + static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators(); + + ModuleBase_ModelWidget* aModelWidget = dynamic_cast(sender()); + if (!aModelWidget || !aModelWidget->feature().get()) + return; + + std::string anAttributeID = aModelWidget->attributeID(); + AttributePtr anAttribute = aModelWidget->feature()->attribute(anAttributeID); + if (!anAttribute.get()) + return; + + std::string aValidatorID; + std::string anErrorMsg; + if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) { + if (anErrorMsg.empty()) + anErrorMsg = "unknown error."; + anErrorMsg = "Attribute \"" + anAttributeID + "\" invalidated by \"" + aValidatorID + "\" with error: " + anErrorMsg; + } + + QString anError = QString::fromStdString(anErrorMsg); + QList aWidgetList = aModelWidget->getControls(); + foreach(QWidget* aWidget, aWidgetList) { + QLabel* aLabel = qobject_cast(aWidget); + // We won't set the effect to QLabels - it looks ugly + if (aLabel) continue; + + // Get the original tool tip of the widget + QString aTTip = aWidget->toolTip().section("Errors:\n", 0, 0).trimmed(); + // Add the error message into the tool tip + if (!anError.isEmpty()) { + if (!aTTip.isEmpty()) + aTTip.append('\n'); + aTTip += "Errors:\n" + anError; + } + aWidget->setToolTip(aTTip); + aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;"); + } +} diff --git a/src/XGUI/XGUI_ErrorMgr.h b/src/XGUI/XGUI_ErrorMgr.h new file mode 100644 index 000000000..36644798c --- /dev/null +++ b/src/XGUI/XGUI_ErrorMgr.h @@ -0,0 +1,31 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: XGUI_ErrorMgr.h +// Created: 22 July 2015 +// Author: Sergey POKHODENKO + +#ifndef XGUI_ErrorMgr_H +#define XGUI_ErrorMgr_H + +#include "XGUI.h" + +#include + +class XGUI_EXPORT XGUI_ErrorMgr : public ModuleBase_IErrorMgr +{ + Q_OBJECT +public: + XGUI_ErrorMgr(QObject* theParent = 0); + /// Virtual destructor + virtual ~XGUI_ErrorMgr(); + +public slots: + /// Reimplemented from ModuleBase_ErrorMgr::onValidationStateChanged(). + virtual void onValidationStateChanged(); + +protected slots: + /// Reimplemented from ModuleBase_ErrorMgr::onWidgetChanged(). + virtual void onWidgetChanged(); +}; + +#endif // XGUI_ErrorMgr_H \ No newline at end of file diff --git a/src/XGUI/XGUI_PropertyPanel.cpp b/src/XGUI/XGUI_PropertyPanel.cpp index 0a9c7189e..4760cffb5 100644 --- a/src/XGUI/XGUI_PropertyPanel.cpp +++ b/src/XGUI/XGUI_PropertyPanel.cpp @@ -56,6 +56,8 @@ XGUI_PropertyPanel::XGUI_PropertyPanel(QWidget* theParent) ModuleBase_Tools::zeroMargins(aBtnLay); aMainLayout->addWidget(aFrm, aPanelRow++, kPanelColumn); + myHeaderWidget = aFrm; + QStringList aBtnNames; aBtnNames << QString(PROP_PANEL_HELP) << QString(PROP_PANEL_OK) diff --git a/src/XGUI/XGUI_PropertyPanel.h b/src/XGUI/XGUI_PropertyPanel.h index 6a982c1c6..9ba7754ed 100644 --- a/src/XGUI/XGUI_PropertyPanel.h +++ b/src/XGUI/XGUI_PropertyPanel.h @@ -50,6 +50,9 @@ Q_OBJECT virtual ~XGUI_PropertyPanel(); + /// Returns header widget + virtual QWidget* headerWidget() const { return myHeaderWidget; } + /// Returns main widget of the property panel, which children will be created /// by WidgetFactory using the XML definition ModuleBase_PageBase* contentWidget(); @@ -108,6 +111,9 @@ Q_OBJECT */ virtual void activateWidget(ModuleBase_ModelWidget* theWidget); + protected: + QWidget* myHeaderWidget; + private: ModuleBase_PageWidget* myPanelPage; QList myWidgets; diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 95db6cca3..294452c6c 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -8,6 +8,7 @@ #include "XGUI_ContextMenuMgr.h" #include "XGUI_Displayer.h" #include "XGUI_ErrorDialog.h" +#include "XGUI_ErrorMgr.h" #include "XGUI_ModuleConnector.h" #include "XGUI_ObjectsBrowser.h" #include "XGUI_OperationMgr.h" @@ -125,6 +126,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector) myOperationMgr = new XGUI_OperationMgr(this, 0); myActionsMgr = new XGUI_ActionsMgr(this); myErrorDlg = new XGUI_ErrorDialog(QApplication::desktop()); + myErrorMgr = new XGUI_ErrorMgr(this); myContextMenuMgr = new XGUI_ContextMenuMgr(this); connect(myContextMenuMgr, SIGNAL(actionTriggered(const QString&, bool)), this, SLOT(onContextMenuCommand(const QString&, bool))); @@ -150,6 +152,9 @@ 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())); + if (myMainWindow) connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit())); connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&))); @@ -483,6 +488,8 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) myModule->propertyPanelDefined(theOperation); myPropertyPanel->setWindowTitle(theOperation->getDescription()->description()); + + myErrorMgr->setPropertyPanel(myPropertyPanel); } /* diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index c0ecf8d73..aa7dfaa76 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -24,6 +24,7 @@ class XGUI_ActionsMgr; class XGUI_ContextMenuMgr; class XGUI_Displayer; class XGUI_ErrorDialog; +class XGUI_ErrorMgr; class XGUI_ModuleConnector; class XGUI_ObjectsBrowser; class XGUI_OperationMgr; @@ -399,6 +400,7 @@ private: private: AppElements_MainWindow* myMainWindow; ModuleBase_IModule* myModule; + XGUI_ErrorMgr* myErrorMgr; XGUI_ObjectsBrowser* myObjectBrowser; XGUI_PropertyPanel* myPropertyPanel; XGUI_SelectionMgr* mySelector; -- 2.39.2