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