Salome HOME
Issue #818 - Deletion of a parameter used in a feature
[modules/shaper.git] / src / XGUI / XGUI_ErrorMgr.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        XGUI_ErrorMgr.cpp
4 // Created:     22 July 2015
5 // Author:      Sergey POKHODENKO
6
7 #include "XGUI_ErrorMgr.h"
8
9 #include "XGUI_OperationMgr.h"
10 #include "XGUI_ModuleConnector.h"
11 #include "XGUI_Workshop.h"
12 #include "XGUI_ActionsMgr.h"
13
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>
19
20 #include <ModelAPI_Attribute.h>
21 #include <ModelAPI_Session.h>
22 #include <ModelAPI_Validator.h>
23
24 #include <QLabel>
25 #include <QAction>
26 #include <QApplication>
27 #include <QDesktopWidget>
28 #include <QDialog>
29 #include <QCursor>
30 #include <QHBoxLayout>
31 #include <QLabel>
32
33 const QString INVALID_VALUE = "invalid_action";
34
35
36 XGUI_ErrorMgr::XGUI_ErrorMgr(QObject* theParent, ModuleBase_IWorkshop* theWorkshop)
37   : ModuleBase_IErrorMgr(theParent),
38     myErrorDialog(0),
39     myErrorLabel(0),
40     myWorkshop(theWorkshop)
41 {
42
43 }
44
45 XGUI_ErrorMgr::~XGUI_ErrorMgr()
46 {
47
48 }
49
50 void XGUI_ErrorMgr::updateActions(const FeaturePtr& theFeature)
51 {
52   QString anError = myWorkshop->module()->getFeatureError(theFeature);
53
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);
61   }
62 }
63
64 void XGUI_ErrorMgr::updateAcceptAllAction(const FeaturePtr& theFeature)
65 {
66   QString anError = myWorkshop->module()->getFeatureError(theFeature);
67
68   XGUI_ActionsMgr* anActionsMgr = workshop()->actionsMgr();
69   if (workshop()->isFeatureOfNested(theFeature)) {
70     QAction* anAcceptAllAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL);
71     bool anEnabled = anError.isEmpty();
72     anAcceptAllAction->setEnabled(anEnabled);
73     anAcceptAllAction->setToolTip(anError);
74   }
75 }
76
77 bool XGUI_ErrorMgr::canProcessClick(QAction* theAction, const FeaturePtr& theFeature)
78 {
79   QString anError = myWorkshop->module()->getFeatureError(theFeature);
80   bool isActionEnabled = anError.isEmpty();
81   if (!isActionEnabled && !anError.isEmpty()) {
82     if (!myErrorDialog) {
83       myErrorDialog = new QDialog(QApplication::desktop(), Qt::Popup);
84       QHBoxLayout* aLay = new QHBoxLayout(myErrorDialog);
85       aLay->setContentsMargins(0, 0, 0, 0);
86
87       QFrame* aMarginWidget = new QFrame(myErrorDialog);
88       aMarginWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
89
90       aLay->addWidget(aMarginWidget);
91       QHBoxLayout* aMarginLay = new QHBoxLayout(aMarginWidget);
92       aMarginLay->setContentsMargins(4, 4, 4, 4);
93
94       myErrorLabel = new QLabel(aMarginWidget);
95       aMarginLay->addWidget(myErrorLabel);
96     }
97     myErrorLabel->setText(anError);
98     myErrorDialog->move(QCursor::pos());
99     myErrorDialog->show();
100   }
101   return isActionEnabled;
102 }
103
104 void XGUI_ErrorMgr::updateActionState(QAction* theAction, const FeaturePtr& theFeature/*,
105                                       const bool theEnabled*/)
106 {
107   QString anError = myWorkshop->module()->getFeatureError(theFeature);
108   bool anEnabled = anError.isEmpty();
109
110   bool isActionEnabled = theAction->data() != INVALID_VALUE;
111   if (anEnabled  != isActionEnabled) {
112     // update enable state of the button
113     theAction->setIcon(anEnabled ? QIcon(":pictures/button_ok.png"): QIcon(":pictures/button_ok_error.png"));
114     if (anEnabled)
115       theAction->setData("");
116     else
117       theAction->setData(INVALID_VALUE);
118   }
119   // some operations have no property panel, so it is important to check that it is not null
120   if (myPropertyPanel) {
121     // update controls error information
122     QWidget* aWidget = myPropertyPanel->headerWidget();
123     if (aWidget)
124       aWidget->setToolTip(anError);
125   }
126 }
127
128 /*const char* toString(ModelAPI_ExecState theExecState) 
129 {
130 #define TO_STRING(__NAME__) case __NAME__: return #__NAME__;
131   switch (theExecState) {
132   TO_STRING(ModelAPI_StateDone)
133   TO_STRING(ModelAPI_StateMustBeUpdated)
134   TO_STRING(ModelAPI_StateExecFailed)
135   TO_STRING(ModelAPI_StateInvalidArgument)
136   TO_STRING(ModelAPI_StateNothing)
137   default: return "Unknown ExecState.";
138   }
139 #undef TO_STRING
140 }*/
141
142 /*void XGUI_ErrorMgr::onValidationStateChanged()
143 {
144   XGUI_OperationMgr* anOperationMgr = dynamic_cast<XGUI_OperationMgr*>(sender());
145   if (!anOperationMgr)
146     return;
147   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
148                                                   (anOperationMgr->currentOperation());
149   if (!myPropertyPanel || !aFOperation)
150     return;
151
152   FeaturePtr aFeature = aFOperation->feature();
153   QString anError = getFeatureError(aFeature);
154
155   QWidget* aWidget = myPropertyPanel->headerWidget();
156   if (aWidget) {
157     aWidget->setToolTip(anError);
158     aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
159   }
160 }*/
161
162 /*QString XGUI_ErrorMgr::getFeatureError(const FeaturePtr& theFeature) const
163 {
164   QString anError;
165   // get feature
166   if (!theFeature.get() || !theFeature->data()->isValid())
167     return anError;
168
169   // set error indication
170   anError = QString::fromStdString(theFeature->error());
171   if (anError.isEmpty()) {
172     bool isDone = ( theFeature->data()->execState() == ModelAPI_StateDone
173                  || theFeature->data()->execState() == ModelAPI_StateMustBeUpdated );
174     if (!isDone)
175       anError = toString(theFeature->data()->execState());
176   }
177
178   return anError;
179 }*/
180
181 void XGUI_ErrorMgr::onWidgetChanged()
182 {
183   static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
184
185   ModuleBase_ModelWidget* aModelWidget = dynamic_cast<ModuleBase_ModelWidget*>(sender());
186   if (!aModelWidget || !aModelWidget->feature().get())
187     return;
188
189   std::string anAttributeID = aModelWidget->attributeID();
190   AttributePtr anAttribute = aModelWidget->feature()->attribute(anAttributeID);
191   if (!anAttribute.get())
192     return;
193
194   std::string aValidatorID;
195   std::string anErrorMsg;
196   if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) {
197     if (anErrorMsg.empty())
198       anErrorMsg = "unknown error.";
199     anErrorMsg = anAttributeID + " - " + aValidatorID + ": " + anErrorMsg;
200   }
201
202   QString anError = QString::fromStdString(anErrorMsg);
203   QList<QWidget*> aWidgetList = aModelWidget->getControls();
204   foreach(QWidget* aWidget, aWidgetList) {
205     QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
206     // We won't set the effect to QLabels - it looks ugly
207     if (aLabel) continue;
208
209     // Get the original tool tip of the widget
210     QString aTTip = aWidget->toolTip().section("Errors:\n", 0, 0).trimmed();
211     // Add the error message into the tool tip
212     if (!anError.isEmpty()) {
213       if (!aTTip.isEmpty())
214         aTTip.append('\n');
215       aTTip += "Errors:\n" + anError;
216     }
217     aWidget->setToolTip(aTTip);
218     //aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
219   }
220 }
221
222 XGUI_Workshop* XGUI_ErrorMgr::workshop() const
223 {
224   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
225   return aConnector->workshop();
226 }