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