Salome HOME
5e59599a3c42b943aa5057b24cb82ae078c2635c
[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 aPattern = QString("[-+]?[0-9]*[%1]?[0-9]+([eE][-+]?[0-9]+)?")
169       .arg(QLocale::system().decimalPoint());
170   QRegExp varNameMask(aPattern);
171   return !varNameMask.exactMatch(theText);
172 }
173
174 /*!
175  \brief This function is used to determine whether input is valid.
176  \return validating operation result
177  */
178 ModuleBase_ParamSpinBox::State ModuleBase_ParamSpinBox::isValid(const QString& theText,
179                                                                 double& theValue) const
180 {
181   if (hasVariable() && !findVariable(theText, theValue)) {
182     bool ok = false;
183     theValue = locale().toDouble(theText, &ok);
184     if (!ok) {
185       return NoVariable;
186     }
187   }
188   if (!checkRange(theValue)) {
189     return Invalid;
190   }
191
192   return Acceptable;
193 }
194
195 /*!
196  \brief This function is used to check that string value lies within predefined range.
197  \return check status
198  */
199 bool ModuleBase_ParamSpinBox::checkRange(const double theValue) const
200 {
201   return theValue >= minimum() && theValue <= maximum();
202 }
203
204 /*!
205  \brief This function is used to determine whether input is a variable name and to get its value.
206  \return status of search operation
207  */
208 bool ModuleBase_ParamSpinBox::findVariable(const QString& theName,
209                                            double& outValue) const
210 {
211   ResultParameterPtr aParam;
212   return ModelAPI_Tools::findVariable(theName.toStdString(), outValue, aParam);
213 }
214
215 /*!
216  \brief This function is called when the spinbox recieves key press event.
217  */
218 void ModuleBase_ParamSpinBox::keyPressEvent(QKeyEvent* e)
219 {
220   if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
221     QWidget::keyPressEvent(e);
222   } else {
223     ModuleBase_DoubleSpinBox::keyPressEvent(e);
224   }
225 }
226
227 /*!
228  \brief This function is called when the spinbox recieves show event.
229  */
230 void ModuleBase_ParamSpinBox::showEvent(QShowEvent* theEvent)
231 {
232   ModuleBase_DoubleSpinBox::showEvent(theEvent);
233   if (hasVariable(myTextValue)) {
234     setText(myTextValue);
235   }
236 }