]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_ErrorMgr.cpp
Salome HOME
Issue #905 Update of invalid feature representation in property panel
[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
11 #include <ModuleBase_IPropertyPanel.h>
12 #include <ModuleBase_ModelWidget.h>
13 #include <ModuleBase_OperationFeature.h>
14
15 #include <ModelAPI_Attribute.h>
16 #include <ModelAPI_Session.h>
17 #include <ModelAPI_Validator.h>
18
19 #include <QLabel>
20 #include <QAction>
21 #include <QApplication>
22 #include <QDesktopWidget>
23 #include <QDialog>
24 #include <QCursor>
25 #include <QHBoxLayout>
26 #include <QLabel>
27
28 const QString INVALID_VALUE = "invalid_action";
29
30
31 XGUI_ErrorMgr::XGUI_ErrorMgr(QObject* theParent /*= 0*/)
32   : ModuleBase_IErrorMgr(theParent),
33     myErrorDialog(0),
34     myErrorLabel(0)
35 {
36
37 }
38
39 XGUI_ErrorMgr::~XGUI_ErrorMgr()
40 {
41
42 }
43
44 bool XGUI_ErrorMgr::canProcessClick(QAction* theAction, const FeaturePtr& theFeature)
45 {
46   QString aData = theAction->data().toString();
47
48   bool isActionEnabled = theAction->data() != INVALID_VALUE;
49
50   QString anError = getFeatureError(theFeature);
51   if (!isActionEnabled && !anError.isEmpty()) {
52     if (!myErrorDialog) {
53       myErrorDialog = new QDialog(QApplication::desktop(), Qt::Popup);
54       QHBoxLayout* aLay = new QHBoxLayout(myErrorDialog);
55       aLay->setContentsMargins(0, 0, 0, 0);
56
57       QFrame* aMarginWidget = new QFrame(myErrorDialog);
58       aMarginWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
59
60       aLay->addWidget(aMarginWidget);
61       QHBoxLayout* aMarginLay = new QHBoxLayout(aMarginWidget);
62       aMarginLay->setContentsMargins(4, 4, 4, 4);
63
64       myErrorLabel = new QLabel(aMarginWidget);
65       aMarginLay->addWidget(myErrorLabel);
66     }
67     myErrorLabel->setText(anError);
68     myErrorDialog->move(QCursor::pos());
69     myErrorDialog->show();
70   }
71   return isActionEnabled;
72 }
73
74 void XGUI_ErrorMgr::updateActionState(QAction* theAction, const FeaturePtr& theFeature,
75                                       const bool theEnabled)
76 {
77   bool isActionEnabled = theAction->data() != INVALID_VALUE;
78   if (theEnabled  != isActionEnabled) {
79     // update enable state of the button
80     theAction->setIcon(theEnabled ? QIcon(":pictures/button_ok.png"): QIcon(":pictures/button_ok_error.png"));
81     if (theEnabled)
82       theAction->setData("");
83     else
84       theAction->setData(INVALID_VALUE);
85   }
86
87   // update controls error information
88   QWidget* aWidget = myPropertyPanel->headerWidget();
89   if (aWidget)
90     aWidget->setToolTip(getFeatureError(theFeature));
91 }
92
93 const char* toString(ModelAPI_ExecState theExecState) 
94 {
95 #define TO_STRING(__NAME__) case __NAME__: return #__NAME__;
96   switch (theExecState) {
97   TO_STRING(ModelAPI_StateDone)
98   TO_STRING(ModelAPI_StateMustBeUpdated)
99   TO_STRING(ModelAPI_StateExecFailed)
100   TO_STRING(ModelAPI_StateInvalidArgument)
101   TO_STRING(ModelAPI_StateNothing)
102   default: return "Unknown ExecState.";
103   }
104 #undef TO_STRING
105 }
106
107 /*void XGUI_ErrorMgr::onValidationStateChanged()
108 {
109   XGUI_OperationMgr* anOperationMgr = dynamic_cast<XGUI_OperationMgr*>(sender());
110   if (!anOperationMgr)
111     return;
112   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
113                                                   (anOperationMgr->currentOperation());
114   if (!myPropertyPanel || !aFOperation)
115     return;
116
117   FeaturePtr aFeature = aFOperation->feature();
118   QString anError = getFeatureError(aFeature);
119
120   QWidget* aWidget = myPropertyPanel->headerWidget();
121   if (aWidget) {
122     aWidget->setToolTip(anError);
123     aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
124   }
125 }*/
126
127 QString XGUI_ErrorMgr::getFeatureError(const FeaturePtr& theFeature) const
128 {
129   QString anError;
130   // get feature
131   if (!theFeature.get() || !theFeature->data()->isValid())
132     return anError;
133
134   // set error indication
135   anError = QString::fromStdString(theFeature->error());
136   if (anError.isEmpty()) {
137     bool isDone = ( theFeature->data()->execState() == ModelAPI_StateDone
138                  || theFeature->data()->execState() == ModelAPI_StateMustBeUpdated );
139     if (!isDone)
140       anError = toString(theFeature->data()->execState());
141   }
142
143   return anError;
144 }
145
146 void XGUI_ErrorMgr::onWidgetChanged()
147 {
148   static ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
149
150   ModuleBase_ModelWidget* aModelWidget = dynamic_cast<ModuleBase_ModelWidget*>(sender());
151   if (!aModelWidget || !aModelWidget->feature().get())
152     return;
153
154   std::string anAttributeID = aModelWidget->attributeID();
155   AttributePtr anAttribute = aModelWidget->feature()->attribute(anAttributeID);
156   if (!anAttribute.get())
157     return;
158
159   std::string aValidatorID;
160   std::string anErrorMsg;
161   if (!aValidators->validate(anAttribute, aValidatorID, anErrorMsg)) {
162     if (anErrorMsg.empty())
163       anErrorMsg = "unknown error.";
164     anErrorMsg = anAttributeID + " - " + aValidatorID + ": " + anErrorMsg;
165   }
166
167   QString anError = QString::fromStdString(anErrorMsg);
168   QList<QWidget*> aWidgetList = aModelWidget->getControls();
169   foreach(QWidget* aWidget, aWidgetList) {
170     QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
171     // We won't set the effect to QLabels - it looks ugly
172     if (aLabel) continue;
173
174     // Get the original tool tip of the widget
175     QString aTTip = aWidget->toolTip().section("Errors:\n", 0, 0).trimmed();
176     // Add the error message into the tool tip
177     if (!anError.isEmpty()) {
178       if (!aTTip.isEmpty())
179         aTTip.append('\n');
180       aTTip += "Errors:\n" + anError;
181     }
182     aWidget->setToolTip(aTTip);
183     //aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
184   }
185 }