1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: XGUI_ErrorMgr.cpp
4 // Created: 22 July 2015
5 // Author: Sergey POKHODENKO
7 #include "XGUI_ErrorMgr.h"
9 #include "XGUI_OperationMgr.h"
10 #include "XGUI_ModuleConnector.h"
11 #include "XGUI_Workshop.h"
12 #include "XGUI_ActionsMgr.h"
14 #include <ModuleBase_IPropertyPanel.h>
15 #include <ModuleBase_IWorkshop.h>
16 #include <ModuleBase_IModule.h>
17 #include <ModuleBase_ModelWidget.h>
18 #include <ModuleBase_OperationFeature.h>
20 #include <ModelAPI_Attribute.h>
21 #include <ModelAPI_Session.h>
22 #include <ModelAPI_Validator.h>
26 #include <QApplication>
27 #include <QDesktopWidget>
30 #include <QHBoxLayout>
33 const QString INVALID_VALUE = "invalid_action";
36 XGUI_ErrorMgr::XGUI_ErrorMgr(QObject* theParent, ModuleBase_IWorkshop* theWorkshop)
37 : ModuleBase_IErrorMgr(theParent),
40 myWorkshop(theWorkshop)
45 XGUI_ErrorMgr::~XGUI_ErrorMgr()
50 void XGUI_ErrorMgr::updateActions(const FeaturePtr& theFeature)
52 QString anError = myWorkshop->module()->getFeatureError(theFeature);
54 //update Ok Action and header of property panel if the current operation started for the feature
55 XGUI_ActionsMgr* anActionsMgr = workshop()->actionsMgr();
56 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
57 (workshop()->operationMgr()->currentOperation());
58 if (aFOperation && aFOperation->feature() == theFeature) {
59 QAction* anOkAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept);
60 updateActionState(anOkAction, theFeature);
62 //update AcceptAll action
63 if (workshop()->isFeatureOfNested(theFeature)) {
64 QAction* anAcceptAllAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL);
65 bool anEnabled = anError.isEmpty();
66 anAcceptAllAction->setEnabled(anEnabled);
67 anAcceptAllAction->setToolTip(anError);
71 bool XGUI_ErrorMgr::canProcessClick(QAction* theAction, const FeaturePtr& theFeature)
73 QString anError = myWorkshop->module()->getFeatureError(theFeature);
74 bool isActionEnabled = anError.isEmpty();
75 if (!isActionEnabled && !anError.isEmpty()) {
77 myErrorDialog = new QDialog(QApplication::desktop(), Qt::Popup);
78 QHBoxLayout* aLay = new QHBoxLayout(myErrorDialog);
79 aLay->setContentsMargins(0, 0, 0, 0);
81 QFrame* aMarginWidget = new QFrame(myErrorDialog);
82 aMarginWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
84 aLay->addWidget(aMarginWidget);
85 QHBoxLayout* aMarginLay = new QHBoxLayout(aMarginWidget);
86 aMarginLay->setContentsMargins(4, 4, 4, 4);
88 myErrorLabel = new QLabel(aMarginWidget);
89 aMarginLay->addWidget(myErrorLabel);
91 myErrorLabel->setText(anError);
92 myErrorDialog->move(QCursor::pos());
93 myErrorDialog->show();
95 return isActionEnabled;
98 void XGUI_ErrorMgr::updateActionState(QAction* theAction, const FeaturePtr& theFeature/*,
99 const bool theEnabled*/)
101 QString anError = myWorkshop->module()->getFeatureError(theFeature);
102 bool anEnabled = anError.isEmpty();
104 bool isActionEnabled = theAction->data() != INVALID_VALUE;
105 if (anEnabled != isActionEnabled) {
106 // update enable state of the button
107 theAction->setIcon(anEnabled ? QIcon(":pictures/button_ok.png"): QIcon(":pictures/button_ok_error.png"));
109 theAction->setData("");
111 theAction->setData(INVALID_VALUE);
113 // some operations have no property panel, so it is important to check that it is not null
114 if (myPropertyPanel) {
115 // update controls error information
116 QWidget* aWidget = myPropertyPanel->headerWidget();
118 aWidget->setToolTip(anError);
122 /*const char* toString(ModelAPI_ExecState theExecState)
124 #define TO_STRING(__NAME__) case __NAME__: return #__NAME__;
125 switch (theExecState) {
126 TO_STRING(ModelAPI_StateDone)
127 TO_STRING(ModelAPI_StateMustBeUpdated)
128 TO_STRING(ModelAPI_StateExecFailed)
129 TO_STRING(ModelAPI_StateInvalidArgument)
130 TO_STRING(ModelAPI_StateNothing)
131 default: return "Unknown ExecState.";
136 /*void XGUI_ErrorMgr::onValidationStateChanged()
138 XGUI_OperationMgr* anOperationMgr = dynamic_cast<XGUI_OperationMgr*>(sender());
141 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
142 (anOperationMgr->currentOperation());
143 if (!myPropertyPanel || !aFOperation)
146 FeaturePtr aFeature = aFOperation->feature();
147 QString anError = getFeatureError(aFeature);
149 QWidget* aWidget = myPropertyPanel->headerWidget();
151 aWidget->setToolTip(anError);
152 aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
156 /*QString XGUI_ErrorMgr::getFeatureError(const FeaturePtr& theFeature) const
160 if (!theFeature.get() || !theFeature->data()->isValid())
163 // set error indication
164 anError = QString::fromStdString(theFeature->error());
165 if (anError.isEmpty()) {
166 bool isDone = ( theFeature->data()->execState() == ModelAPI_StateDone
167 || theFeature->data()->execState() == ModelAPI_StateMustBeUpdated );
169 anError = toString(theFeature->data()->execState());
175 void XGUI_ErrorMgr::onWidgetChanged()
177 static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
179 ModuleBase_ModelWidget* aModelWidget = dynamic_cast<ModuleBase_ModelWidget*>(sender());
180 if (!aModelWidget || !aModelWidget->feature().get())
183 std::string anAttributeID = aModelWidget->attributeID();
184 AttributePtr anAttribute = aModelWidget->feature()->attribute(anAttributeID);
185 if (!anAttribute.get())
188 std::string aValidatorID;
189 std::string anErrorMsg;
190 if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) {
191 if (anErrorMsg.empty())
192 anErrorMsg = "unknown error.";
193 anErrorMsg = anAttributeID + " - " + aValidatorID + ": " + anErrorMsg;
196 QString anError = QString::fromStdString(anErrorMsg);
197 QList<QWidget*> aWidgetList = aModelWidget->getControls();
198 foreach(QWidget* aWidget, aWidgetList) {
199 QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
200 // We won't set the effect to QLabels - it looks ugly
201 if (aLabel) continue;
203 // Get the original tool tip of the widget
204 QString aTTip = aWidget->toolTip().section("Errors:\n", 0, 0).trimmed();
205 // Add the error message into the tool tip
206 if (!anError.isEmpty()) {
207 if (!aTTip.isEmpty())
209 aTTip += "Errors:\n" + anError;
211 aWidget->setToolTip(aTTip);
212 //aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
216 XGUI_Workshop* XGUI_ErrorMgr::workshop() const
218 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
219 return aConnector->workshop();