Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom.git into Dev_1.1.0
[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 <QToolTip>
12 #include <QRegExp>
13
14 #include <string>
15 #include <iostream>
16
17 /*!
18  \class ModuleBase_ParamSpinBox
19  */
20
21 /*!
22  \brief Constructor.
23
24  Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value,
25  a step value of 1.0 and a precision of 2 decimal places.
26  The value is initially set to 0.00.
27
28  \param parent parent object
29  */
30 ModuleBase_ParamSpinBox::ModuleBase_ParamSpinBox(QWidget* theParent, int thePrecision)
31     : ModuleBase_DoubleSpinBox(theParent, thePrecision),
32       myAcceptVariables(true)
33 {
34   connectSignalsAndSlots();
35 }
36
37 /*!
38  \brief Destructor.
39  */
40 ModuleBase_ParamSpinBox::~ModuleBase_ParamSpinBox()
41 {
42 }
43
44 /*!
45  \brief Perform \a steps increment/decrement steps.
46
47  Re-implemented to handle cases when Notebook variable
48  name is specified by the user as the widget text.
49  Otherwise, simply calls the base implementation.
50
51  \param steps number of increment/decrement steps
52  */
53 void ModuleBase_ParamSpinBox::stepBy(int steps)
54 {
55   if (hasVariable())
56     return;
57
58   ModuleBase_DoubleSpinBox::stepBy(steps);
59 }
60
61 /*!
62  \brief Connect signals and slots.
63  */
64 void ModuleBase_ParamSpinBox::connectSignalsAndSlots()
65 {
66   connect(this, SIGNAL(valueChanged(const QString&)),
67           this, SLOT(onTextChanged(const QString&)));
68 }
69
70 /*!
71  \brief This function is called when value is changed.
72  */
73 void ModuleBase_ParamSpinBox::onTextChanged(const QString& text)
74 {
75   myTextValue = text;
76 }
77
78 /*!
79  \brief Interpret text entered by the user as a value.
80  \param text text entered by the user
81  \return mapped value
82  \sa textFromValue()
83  */
84 double ModuleBase_ParamSpinBox::valueFromText(const QString& theText) const
85 {
86   if (!hasVariable(theText))
87     return ModuleBase_DoubleSpinBox::valueFromText(theText);
88
89   double aValue = 0;
90   findVariable(theText, aValue);
91   return aValue;
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
116   // Considering the input text as a variable name
117   // Applying Python identifier syntax:
118   // either a string starting with a letter, or a string starting with
119   // an underscore followed by at least one alphanumeric character
120   if (isAcceptVariables()) {
121     QRegExp varNameMask("[_a-zA-Z][a-zA-Z0-9_]*");
122     if (varNameMask.exactMatch(str))
123       res = QValidator::Acceptable;
124
125     if (res == QValidator::Invalid) {
126       varNameMask.setPattern("_");
127       if (varNameMask.exactMatch(str))
128         res = QValidator::Intermediate;
129     }
130   }
131   return res;
132 }
133
134 /*!
135  \brief This function is used to set a current value for this spinbox.
136  \param value current value
137  */
138 void ModuleBase_ParamSpinBox::setValue(const double value)
139 {
140   ModuleBase_DoubleSpinBox::setValue(value);
141
142   myTextValue = ModuleBase_DoubleSpinBox::textFromValue(value);
143 }
144
145 /*!
146  \brief This function is used to set a text for this spinbox.
147  \param value current value
148  */
149 void ModuleBase_ParamSpinBox::setText(const QString& value)
150 {
151   lineEdit()->setText(value);
152 }
153
154 /*!
155  \brief Enables or disables variable names in the spin box.
156  By default, variable names are enabled.
157  \param flag If true, variable names are enabled.
158  */
159 void ModuleBase_ParamSpinBox::setAcceptVariables(const bool flag)
160 {
161   myAcceptVariables = flag;
162 }
163
164 /*!
165  \brief Returns true if the spin box accepts variable names.
166  */
167 bool ModuleBase_ParamSpinBox::isAcceptVariables() const
168 {
169   return myAcceptVariables;
170 }
171
172 bool ModuleBase_ParamSpinBox::hasVariable() const
173 {
174   return hasVariable(myTextValue);
175 }
176
177 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
178 {
179   QRegExp varNameMask("([a-z]|[A-Z]|_).*");
180   return varNameMask.exactMatch(theText);
181 }
182
183 /*!
184  \brief This function is used to determine whether input is valid.
185  \return validating operation result
186  */
187 ModuleBase_ParamSpinBox::State ModuleBase_ParamSpinBox::isValid(const QString& theText,
188                                                                 double& theValue) const
189 {
190   if (hasVariable() && !findVariable(theText, theValue)) {
191     bool ok = false;
192     theValue = locale().toDouble(theText, &ok);
193     if (!ok) {
194       return NoVariable;
195     }
196   }
197   if (!checkRange(theValue)) {
198     return Invalid;
199   }
200
201   return Acceptable;
202 }
203
204 /*!
205  \brief This function is used to check that string value lies within predefined range.
206  \return check status
207  */
208 bool ModuleBase_ParamSpinBox::checkRange(const double theValue) const
209 {
210   return theValue >= minimum() && theValue <= maximum();
211 }
212
213 /*!
214  \brief This function is used to determine whether input is a variable name and to get its value.
215  \return status of search operation
216  */
217 bool ModuleBase_ParamSpinBox::findVariable(const QString& theName,
218                                            double& outValue) const
219 {
220
221   return ModelAPI_Tools::findVariable(theName.toStdString(), outValue);
222 }
223
224 /*!
225  \brief This function is called when the spinbox recieves key press event.
226  */
227 void ModuleBase_ParamSpinBox::keyPressEvent(QKeyEvent* e)
228 {
229   if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
230     QWidget::keyPressEvent(e);
231   } else {
232     ModuleBase_DoubleSpinBox::keyPressEvent(e);
233   }
234 }
235
236 /*!
237  \brief This function is called when the spinbox recieves show event.
238  */
239 void ModuleBase_ParamSpinBox::showEvent(QShowEvent* theEvent)
240 {
241   ModuleBase_DoubleSpinBox::showEvent(theEvent);
242   if (hasVariable(myTextValue)) {
243     setText(myTextValue);
244   }
245 }