Salome HOME
34f7bcb6d25339de0e11febd42a10088db438342
[modules/shaper.git] / src / ModuleBase / ModuleBase_ParamSpinBox.cpp
1 #include "ModuleBase_ParamSpinBox.h"
2
3 #include <ModelAPI_Session.h>
4 #include <ModelAPI_Document.h>
5 #include <ModelAPI_ResultParameter.h>
6 #include <ModelAPI_AttributeDouble.h>
7 #include <ModelAPI_Tools.h>
8
9 #include <QKeyEvent>
10 #include <QLineEdit>
11 #include <QLocale>
12 #include <QRegExp>
13 #include <QToolTip>
14
15 #include <string>
16 #include <iostream>
17
18 /*!
19  \class ModuleBase_ParamSpinBox
20  */
21
22 /*!
23  \brief Constructor.
24
25  Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value,
26  a step value of 1.0 and a precision of 2 decimal places.
27  The value is initially set to 0.00.
28
29  \param parent parent object
30  */
31 ModuleBase_ParamSpinBox::ModuleBase_ParamSpinBox(QWidget* theParent, int thePrecision)
32     : ModuleBase_DoubleSpinBox(theParent, thePrecision),
33       myAcceptVariables(true)
34 {
35   connectSignalsAndSlots();
36 }
37
38 /*!
39  \brief Destructor.
40  */
41 ModuleBase_ParamSpinBox::~ModuleBase_ParamSpinBox()
42 {
43 }
44
45 /*!
46  \brief Perform \a steps increment/decrement steps.
47
48  Re-implemented to handle cases when Notebook variable
49  name is specified by the user as the widget text.
50  Otherwise, simply calls the base implementation.
51
52  \param steps number of increment/decrement steps
53  */
54 void ModuleBase_ParamSpinBox::stepBy(int steps)
55 {
56   if (hasVariable())
57     return;
58
59   ModuleBase_DoubleSpinBox::stepBy(steps);
60 }
61
62 /*!
63  \brief Connect signals and slots.
64  */
65 void ModuleBase_ParamSpinBox::connectSignalsAndSlots()
66 {
67   connect(this, SIGNAL(valueChanged(const QString&)),
68           this, SLOT(onTextChanged(const QString&)));
69 }
70
71 /*!
72  \brief This function is called when value is changed.
73  */
74 void ModuleBase_ParamSpinBox::onTextChanged(const QString& text)
75 {
76   myTextValue = text;
77 }
78
79 /*!
80  \brief Interpret text entered by the user as a value.
81  \param text text entered by the user
82  \return mapped value
83  \sa textFromValue()
84  */
85 double ModuleBase_ParamSpinBox::valueFromText(const QString& theText) const
86 {
87   if (!hasVariable(theText)) {
88     return ModuleBase_DoubleSpinBox::valueFromText(theText);
89   }
90   // small hack: return length of the string to iniiate valuesChanged signal
91   return theText.length();
92 }
93
94 QString ModuleBase_ParamSpinBox::textFromValue (double theValue) const
95 {
96   if (hasVariable(myTextValue)){
97     return myTextValue;
98   }
99   return ModuleBase_DoubleSpinBox::textFromValue(theValue);
100 }
101
102 /*!
103  \brief This function is used to determine whether input is valid.
104  \param str currently entered value
105  \param pos cursor position in the string
106  \return validating operation result
107  */
108 QValidator::State ModuleBase_ParamSpinBox::validate(QString& str, int& pos) const
109 {
110   // Trying to interpret the current input text as a numeric value
111   if (!hasVariable(str))
112     return ModuleBase_DoubleSpinBox::validate(str, pos);
113
114   QValidator::State res = QValidator::Invalid;
115   if (isAcceptVariables()) {
116     res = QValidator::Acceptable;
117   }
118   return res;
119 }
120
121 /*!
122  \brief This function is used to set a current value for this spinbox.
123  \param value current value
124  */
125 void ModuleBase_ParamSpinBox::setValue(const double value)
126 {
127   ModuleBase_DoubleSpinBox::setValue(value);
128
129   myTextValue = ModuleBase_DoubleSpinBox::textFromValue(value);
130 }
131
132 /*!
133  \brief This function is used to set a text for this spinbox.
134  \param value current value
135  */
136 void ModuleBase_ParamSpinBox::setText(const QString& value)
137 {
138   lineEdit()->setText(value);
139 }
140
141 /*!
142  \brief Enables or disables variable names in the spin box.
143  By default, variable names are enabled.
144  \param flag If true, variable names are enabled.
145  */
146 void ModuleBase_ParamSpinBox::setAcceptVariables(const bool flag)
147 {
148   myAcceptVariables = flag;
149 }
150
151 /*!
152  \brief Returns true if the spin box accepts variable names.
153  */
154 bool ModuleBase_ParamSpinBox::isAcceptVariables() const
155 {
156   return myAcceptVariables;
157 }
158
159 bool ModuleBase_ParamSpinBox::hasVariable() const
160 {
161   if (myTextValue.isEmpty())
162     return false;
163   return hasVariable(myTextValue);
164 }
165
166 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
167 {
168   QString aDigitPattern = QString("[-+]?[0-9]*[%1]?[0-9]+([eE][-+]?[0-9]+)?");
169
170   bool aHasDigit = false;
171   {
172     QRegExp varNameMask(aDigitPattern.arg("."));
173     aHasDigit = varNameMask.exactMatch(theText);
174   }
175   if (!aHasDigit)
176   {
177     QRegExp varNameMask(aDigitPattern.arg(","));
178     aHasDigit = varNameMask.exactMatch(theText);
179   }
180
181   return !aHasDigit;
182
183 }
184
185 /*!
186  \brief This function is used to determine whether input is valid.
187  \return validating operation result
188  */
189 ModuleBase_ParamSpinBox::State ModuleBase_ParamSpinBox::isValid(const QString& theText,
190                                                                 double& theValue) const
191 {
192   if (hasVariable() && !findVariable(theText, theValue)) {
193     bool ok = false;
194     theValue = locale().toDouble(theText, &ok);
195     if (!ok) {
196       return NoVariable;
197     }
198   }
199   if (!checkRange(theValue)) {
200     return Invalid;
201   }
202
203   return Acceptable;
204 }
205
206 /*!
207  \brief This function is used to check that string value lies within predefined range.
208  \return check status
209  */
210 bool ModuleBase_ParamSpinBox::checkRange(const double theValue) const
211 {
212   return theValue >= minimum() && theValue <= maximum();
213 }
214
215 /*!
216  \brief This function is used to determine whether input is a variable name and to get its value.
217  \return status of search operation
218  */
219 bool ModuleBase_ParamSpinBox::findVariable(const QString& theName,
220                                            double& outValue) const
221 {
222   ResultParameterPtr aParam;
223   return ModelAPI_Tools::findVariable(theName.toStdString(), outValue, aParam);
224 }
225
226 /*!
227  \brief This function is called when the spinbox recieves key press event.
228  */
229 void ModuleBase_ParamSpinBox::keyPressEvent(QKeyEvent* e)
230 {
231   if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
232     QWidget::keyPressEvent(e);
233   } else {
234     ModuleBase_DoubleSpinBox::keyPressEvent(e);
235   }
236 }
237
238 /*!
239  \brief This function is called when the spinbox recieves show event.
240  */
241 void ModuleBase_ParamSpinBox::showEvent(QShowEvent* theEvent)
242 {
243   ModuleBase_DoubleSpinBox::showEvent(theEvent);
244   if (hasVariable(myTextValue)) {
245     setText(myTextValue);
246   }
247 }