Salome HOME
Merge branch 'BR_EDF_2018_Lot1'
[modules/shaper.git] / src / XGUI / XGUI_ErrorMgr.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "XGUI_ErrorMgr.h"
22
23 #include "XGUI_OperationMgr.h"
24 #include "XGUI_ModuleConnector.h"
25 #include "XGUI_Workshop.h"
26 #include "XGUI_ActionsMgr.h"
27
28 #include <ModuleBase_IPropertyPanel.h>
29 #include <ModuleBase_IWorkshop.h>
30 #include <ModuleBase_IModule.h>
31 #include <ModuleBase_ModelWidget.h>
32 #include <ModuleBase_OperationFeature.h>
33
34 #include <ModuleBase_Tools.h>
35 #include <QDebug>
36
37 #include <ModelAPI_Attribute.h>
38 #include <ModelAPI_Session.h>
39 #include <ModelAPI_Validator.h>
40
41 #include <QLabel>
42 #include <QAction>
43 #include <QApplication>
44 #include <QDesktopWidget>
45 #include <QDialog>
46 #include <QCursor>
47 #include <QHBoxLayout>
48 #include <QLabel>
49
50 const QString INVALID_VALUE = "invalid_action";
51
52 //#define DEBUG_ERROR_STATE
53
54 XGUI_ErrorMgr::XGUI_ErrorMgr(QObject* theParent, ModuleBase_IWorkshop* theWorkshop)
55   : ModuleBase_IErrorMgr(theParent),
56     myErrorDialog(0),
57     myErrorLabel(0),
58     myWorkshop(theWorkshop),
59     myAcceptAllToolTip(""),
60     myAcceptAllStatusTip(""),
61     myAcceptToolTip(""),
62     myAcceptStatusTip("")
63 {
64 }
65
66 XGUI_ErrorMgr::~XGUI_ErrorMgr()
67 {
68 }
69
70 void XGUI_ErrorMgr::updateActions(const FeaturePtr& theFeature)
71 {
72   //update Ok Action and header of property panel if the current operation started for the feature
73   XGUI_ActionsMgr* anActionsMgr = workshop()->actionsMgr();
74   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
75                                       (workshop()->operationMgr()->currentOperation());
76   if (aFOperation && aFOperation->feature() == theFeature) {
77     ModuleBase_ModelWidget* anActiveWidget = activeWidget();
78     bool isApplyEnabledByActiveWidget = false;
79     if (anActiveWidget)
80       isApplyEnabledByActiveWidget = anActiveWidget->getValueState() ==
81                                      ModuleBase_ModelWidget::ModifiedInPP;
82     QString anError = "";
83     QString aWidgetError = "";
84     if (!isApplyEnabledByActiveWidget) {
85       anError = myWorkshop->module()->getFeatureError(theFeature);
86       if (anActiveWidget)
87         aWidgetError = anActiveWidget->getError();
88       if (anError.isEmpty())
89         anError = aWidgetError;
90     }
91     updateAcceptActionState(anError);
92     updateToolTip(anActiveWidget, aWidgetError);
93     myWorkshop->setStatusBarMessage(anError);
94
95 #ifdef DEBUG_ERROR_STATE
96     QString anInfo = ModuleBase_Tools::objectInfo(theFeature);
97
98     QString aResultInfo = QString("valid = %1, anError = %2, aWidgetError = %3")
99                           .arg(anError.isEmpty()).arg(anError).arg(aWidgetError);
100     qDebug(QString("XGUI_ErrorMgr::updateActions for %1, result: %2").arg(anInfo)
101                   .arg(aResultInfo).toStdString().c_str());
102 #endif
103   }
104 }
105
106 void XGUI_ErrorMgr::updateAcceptAllAction(const FeaturePtr& theFeature)
107 {
108   if (myAcceptAllToolTip.isEmpty() && myAcceptToolTip.isEmpty())
109     storeInitialActionValues();
110
111   QString anError = "";
112   /// to allow the module have the button always enabled
113   bool isActionStateEnabled =
114     myWorkshop->module()->isActionEnableStateFixed(XGUI_ActionsMgr::AcceptAll);
115   if (!isActionStateEnabled) {
116     anError = myWorkshop->module()->getFeatureError(theFeature);
117     if (anError.isEmpty()) {
118       ModuleBase_ModelWidget* anActiveWidget = activeWidget();
119       if (anActiveWidget)
120         anError = anActiveWidget->getError();
121     }
122   }
123   XGUI_ActionsMgr* anActionsMgr = workshop()->actionsMgr();
124   if (workshop()->isFeatureOfNested(theFeature)) {
125     QAction* anAcceptAllAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll);
126     bool anEnabled = anError.isEmpty();
127     anAcceptAllAction->setEnabled(anEnabled);
128     anAcceptAllAction->setToolTip(!anEnabled ? anError : myAcceptAllToolTip);
129     anAcceptAllAction->setStatusTip(!anEnabled ? anError : myAcceptAllStatusTip);
130   }
131 }
132
133 bool XGUI_ErrorMgr::isApplyEnabled() const
134 {
135   bool isEnabled = false;
136   XGUI_ActionsMgr* anActionsMgr = workshop()->actionsMgr();
137   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
138                                       (workshop()->operationMgr()->currentOperation());
139   if (aFOperation) {
140     QAction* anOkAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept);
141     isEnabled = anOkAction && anOkAction->isEnabled();
142   }
143   return isEnabled;
144 }
145
146 void XGUI_ErrorMgr::storeInitialActionValues()
147 {
148   ModuleBase_ModelWidget* anActiveWidget = activeWidget();
149   XGUI_ActionsMgr* anActionsMgr = workshop()->actionsMgr();
150   QAction* anAcceptAllAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll);
151   myAcceptAllToolTip = anAcceptAllAction->toolTip();
152   myAcceptAllStatusTip = anAcceptAllAction->statusTip();
153
154   QAction* anOkAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept);
155   myAcceptToolTip = anOkAction->toolTip();
156   myAcceptStatusTip = anOkAction->toolTip();
157 }
158
159 void XGUI_ErrorMgr::updateAcceptActionState(const QString& theError)
160 {
161   XGUI_ActionsMgr* anActionsMgr = workshop()->actionsMgr();
162   QAction* anAcceptAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept);
163   QAction* anAcceptPlusAction =
164     anActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptPlus);
165
166   if (myAcceptAllToolTip.isEmpty() && myAcceptToolTip.isEmpty())
167     storeInitialActionValues();
168
169   bool anEnabled = theError.isEmpty();
170   anAcceptAction->setEnabled(anEnabled);
171   anAcceptPlusAction->setEnabled(anEnabled);
172   anAcceptAction->setToolTip(anEnabled ? myAcceptToolTip : theError);
173   anAcceptAction->setStatusTip(anEnabled ? myAcceptStatusTip : theError);
174   // some operations have no property panel, so it is important to check that it is not null
175   if (myPropertyPanel) {
176     // update controls error information
177     QWidget* aWidget = myPropertyPanel->headerWidget();
178     if (aWidget)
179       aWidget->setToolTip(theError);
180   }
181 }
182 void XGUI_ErrorMgr::onWidgetChanged()
183 {
184   ModuleBase_ModelWidget* aModelWidget = dynamic_cast<ModuleBase_ModelWidget*>(sender());
185   if (!aModelWidget || !aModelWidget->feature().get())
186     return;
187
188   QString aWidgetError = aModelWidget->getError();
189   updateToolTip(aModelWidget, aWidgetError);
190 }
191
192 void XGUI_ErrorMgr::updateToolTip(ModuleBase_ModelWidget* theWidget,
193                                   const QString& theError)
194 {
195   if (!theWidget)
196     return;
197
198   QList<QWidget*> aWidgetList = theWidget->getControls();
199   foreach(QWidget* aWidget, aWidgetList) {
200     QLabel* aLabel = qobject_cast<QLabel*>(aWidget);
201     // We won't set the effect to QLabels - it looks ugly
202     if (aLabel) continue;
203
204     // Get the original tool tip of the widget
205     QString aTTip = aWidget->toolTip().section("Errors:\n", 0, 0).trimmed();
206     // Add the error message into the tool tip
207     if (!theError.isEmpty()) {
208       if (!aTTip.isEmpty())
209         aTTip.append('\n');
210       aTTip += "Errors:\n" + theError;
211     }
212     aWidget->setToolTip(aTTip);
213     //aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
214   }
215 }
216
217 XGUI_Workshop* XGUI_ErrorMgr::workshop() const
218 {
219   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
220   return aConnector->workshop();
221 }
222
223 ModuleBase_ModelWidget* XGUI_ErrorMgr::activeWidget() const
224 {
225   ModuleBase_ModelWidget* anActiveWidget = 0;
226
227   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
228                                       (workshop()->operationMgr()->currentOperation());
229   if (aFOperation) {
230     ModuleBase_IPropertyPanel* aPropertyPanel = aFOperation->propertyPanel();
231     if (aPropertyPanel) {
232       anActiveWidget = aPropertyPanel->activeWidget();
233     }
234   }
235   return anActiveWidget;
236 }
237