Salome HOME
Issue #971: Update OB on duplicate part: send event on creation of a new document...
[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   theAction->setEnabled(anEnabled);
120   // some operations have no property panel, so it is important to check that it is not null
121   if (myPropertyPanel) {
122     // update controls error information
123     QWidget* aWidget = myPropertyPanel->headerWidget();
124     if (aWidget)
125       aWidget->setToolTip(anError);
126   }
127 }
128
129 /*const char* toString(ModelAPI_ExecState theExecState) 
130 {
131 #define TO_STRING(__NAME__) case __NAME__: return #__NAME__;
132   switch (theExecState) {
133   TO_STRING(ModelAPI_StateDone)
134   TO_STRING(ModelAPI_StateMustBeUpdated)
135   TO_STRING(ModelAPI_StateExecFailed)
136   TO_STRING(ModelAPI_StateInvalidArgument)
137   TO_STRING(ModelAPI_StateNothing)
138   default: return "Unknown ExecState.";
139   }
140 #undef TO_STRING
141 }*/
142
143 /*void XGUI_ErrorMgr::onValidationStateChanged()
144 {
145   XGUI_OperationMgr* anOperationMgr = dynamic_cast<XGUI_OperationMgr*>(sender());
146   if (!anOperationMgr)
147     return;
148   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
149                                                   (anOperationMgr->currentOperation());
150   if (!myPropertyPanel || !aFOperation)
151     return;
152
153   FeaturePtr aFeature = aFOperation->feature();
154   QString anError = getFeatureError(aFeature);
155
156   QWidget* aWidget = myPropertyPanel->headerWidget();
157   if (aWidget) {
158     aWidget->setToolTip(anError);
159     aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
160   }
161 }*/
162
163 /*QString XGUI_ErrorMgr::getFeatureError(const FeaturePtr& theFeature) const
164 {
165   QString anError;
166   // get feature
167   if (!theFeature.get() || !theFeature->data()->isValid())
168     return anError;
169
170   // set error indication
171   anError = QString::fromStdString(theFeature->error());
172   if (anError.isEmpty()) {
173     bool isDone = ( theFeature->data()->execState() == ModelAPI_StateDone
174                  || theFeature->data()->execState() == ModelAPI_StateMustBeUpdated );
175     if (!isDone)
176       anError = toString(theFeature->data()->execState());
177   }
178
179   return anError;
180 }*/
181
182 void XGUI_ErrorMgr::onWidgetChanged()
183 {
184   static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
185
186   ModuleBase_ModelWidget* aModelWidget = dynamic_cast<ModuleBase_ModelWidget*>(sender());
187   if (!aModelWidget || !aModelWidget->feature().get())
188     return;
189
190   std::string anAttributeID = aModelWidget->attributeID();
191   AttributePtr anAttribute = aModelWidget->feature()->attribute(anAttributeID);
192   if (!anAttribute.get())
193     return;
194
195   std::string aValidatorID;
196   std::string anErrorMsg;
197   if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) {
198     if (anErrorMsg.empty())
199       anErrorMsg = "unknown error.";
200     anErrorMsg = anAttributeID + " - " + aValidatorID + ": " + anErrorMsg;
201   }
202
203   QString anError = QString::fromStdString(anErrorMsg);
204   QList<QWidget*> aWidgetList = aModelWidget->getControls();
205   foreach(QWidget* aWidget, aWidgetList) {
206     QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
207     // We won't set the effect to QLabels - it looks ugly
208     if (aLabel) continue;
209
210     // Get the original tool tip of the widget
211     QString aTTip = aWidget->toolTip().section("Errors:\n", 0, 0).trimmed();
212     // Add the error message into the tool tip
213     if (!anError.isEmpty()) {
214       if (!aTTip.isEmpty())
215         aTTip.append('\n');
216       aTTip += "Errors:\n" + anError;
217     }
218     aWidget->setToolTip(aTTip);
219     //aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
220   }
221 }
222
223 XGUI_Workshop* XGUI_ErrorMgr::workshop() const
224 {
225   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
226   return aConnector->workshop();
227 }