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