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